堆结构介绍
堆是一种数据结构,在逻辑上是一颗完全二叉树,在存储上是一个数组。堆有大顶堆、和小顶堆之分,大顶堆:对于每个父节点而言,其左右子节点都是小于父节点的,所以根节点也就是堆顶保存的是堆内最大的元素;小顶堆:每个父节点的值都是小于子节点的,堆顶保存堆内最小的元素。
堆的存储
上面已经介绍了堆是用数组来存储的,但是怎么来存呢?其实就是把一棵完全二叉树按层遍历后的顺序依次放入一个数组里面是一样的,比如下面的一颗完全二叉树:
对应存储数组:
除此之外我们还需要知道父节点和子节点在数组中索引的一些关系:
当前节点索引为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