堆結構介紹
堆是一種數據結構,在邏輯上是一顆完全二叉樹,在存儲上是一個數組。堆有大頂堆、和小頂堆之分,大頂堆:對於每個父節點而言,其左右子節點都是小於父節點的,所以根節點也就是堆頂保存的是堆內最大的元素;小頂堆:每個父節點的值都是小於子節點的,堆頂保存堆內最小的元素。
堆的存儲
上面已經介紹了堆是用數組來存儲的,但是怎麼來存呢?其實就是把一棵完全二叉樹按層遍歷後的順序依次放入一個數組裏面是一樣的,比如下面的一顆完全二叉樹:
對應存儲數組:
除此之外我們還需要知道父節點和子節點在數組中索引的一些關係:
當前節點索引爲i
則:
左子節點索引:2 * i + 1
右子節點索引:2 * i + 2
父節點索引:(i - 1) / 2
堆的基本操作(這裏以大頂堆爲例)
上浮: 將當前位置i
對應的元素向上移動,如果父節點小於當前值就交換,此時當前位置就更新到父節點的位置,然後繼續和父節點判斷重複此過程直到不能交換爲止。
對應代碼:
void seekUp(int i)
{
while (i >= 0)
{
if (heap[i] > heap[(i - 1) / 2])
swap(heap[i], heap[(i - 1) / 2]);
else
return;
i = (i - 1) / 2;
}
}
下沉: 將當前位置i
對應的元素向下移動,如果子節點大於當前值就交換(如果左右子節點值都大於父節點則選值最大的子節點),此時當前位置就更新到所交換的子節點的位置,然後繼續和子節點節點判斷重複此過程直到不能交換爲止。
void seekDown(int i)
{
while (i < n)
{
int maxIdx = i;
int leftIdx = i * 2 + 1;
int rightIdx = i * 2 + 2;
if(leftIdx < n && heap[leftIdx] > heap[maxIdx]) maxIdx = leftIdx;
if(rightIdx < n && heap[rightIdx] > heap[maxIdx]) maxIdx = rightIdx;
if(maxIdx != i) swap(heap[maxIdx], heap[i]);
else return;
}
}
刪除: 將數組的最後一個元數賦值爲堆頂然後進行下層操作
void deleteHeap()
{
heap[0] = heap[--n];
seekDown(0);
}
插入: 在數組的末尾添加一個元數然後進行上浮操作
void insertHeap(int val)
{
heap[n++]=val;
seekUp(n-1);
}
整體代碼
class HEAD
{
public:
HEAD() { n = 0; heap.resize(1000, 0); }
HEAD(vector<int> v) :heap(v) { n = v.size(); }
//插入
void insertHeap(int val)
{
heap[n++] = val;
seekUp(n - 1);
}
//刪除
void deleteHeap()
{
heap[0] = heap[--n];
seekDown(0);
}
//獲取頂端的值
int getVal()
{
if (n == 0)
return INT_MIN;
return heap[0];
}
//下沉
void seekDown(int i)
{
while (i < n)
{
int maxIdx = i;
int leftIdx = i * 2 + 1;
int rightIdx = i * 2 + 2;
if (leftIdx < n && heap[leftIdx] > heap[maxIdx]) maxIdx = leftIdx;
if (rightIdx < n && heap[rightIdx] > heap[maxIdx]) maxIdx = rightIdx;
if (maxIdx != i) swap(heap[maxIdx], heap[i]);
else return;
}
}
//上浮
void seekUp(int i)
{
while (i >= 0)
{
if (heap[i] > heap[(i - 1) / 2])
swap(heap[i], heap[(i - 1) / 2]);
else
return;
i = (i - 1) / 2;
}
}
void printHeap()
{
for (int i = 0; i < n; i++)
cout << heap[i] << " ";
cout << endl;
}
private:
vector<int> heap;
int n;
};
int main()
{
HEAD h;
h.insertHeap(5);
h.insertHeap(14);
h.insertHeap(4);
h.printHeap();
h.deleteHeap();
h.printHeap();
return 0;
}
運行結果:
14 5 4
5 4