堆-数组实现
堆,利用完全二叉树的结构来维护一组数据。
满二叉树: 除最后一层无任何子节点外,每一层的所有结点都有两个子节点的二叉树。也就是说每层节点数都达到最大值。
完全二叉树: 最后一层的所有结点都连续集中在最左边。除此之外都是满的。
最大堆,就是root是这棵树最大的值。优先级队列。c++中包含头文件#include <queue> 后用priority_queue <T> s 来使用,默认最大堆。
堆的维护主要需掌握一下几个操作:
- pop。即删掉堆顶的操作,就把最后一个点放到堆顶,然后再往下面逐个比较,如果大的就交换位置
int Remove_Heap(HeapChain_idx H, int &e)
{
if(H->sizee == 0)
return 0;
e = H->Element[1];
H->Element[1] = H->Element[H->sizee--]; ///用最后一个数将堆顶覆盖
int parent, child;
for(parent = 1; parent * 2 <= H->sizee; parent = child) ///将堆顶数往满足堆定义的位置移动
{
child = parent * 2;
if(child < H->sizee && H->Element[child] < H->Element[child+1]) ///找出左右子节点的较大者
child++;
if(H->Element[parent] < H->Element[child]) ///如果比子节点最大者小就往下移动
{
int t;
t = H->Element[parent], H->Element[parent] = H->Element[child], H->Element[child] = t;
}
else ///否则就比两个子节点都大或相等,满足堆定义。调整完成
break;
}
return 1;
}
- push操作。插入的话,就比较大小,如果插入点比父节点大,那么就直接交换。操作时,可用父节点逐级向上交换值,直到找到插入点的位置
int In_Heap(HeapChain_idx H, int x)
{
if(H->sizee >= H->capacity)
return 0;
int i = ++H->sizee;
for( ; H->Element[i/2] < x; i /= 2) ///插入的数只要比父节点大,父节点的值就往下移
H->Element[i] = H->Element[i/2];
H->Element[i] = x;
return 1;
}
- 从数组中维护一个堆。即对所有父节点,采用维护操作即可。每次对父节点维护,可保证其子树维持堆性质。
int Adjust_Heap(HeapChain_idx H)
{
if(H->sizee == 0)
return 0;
for(int k = H->sizee/2; k > 0; k--) ///从最后一个节点的父节点调整使满足堆定义,调整至堆顶
{
int parent, child;
for(parent = k; parent * 2 <= H->sizee; parent = child) ///如果当前节点要比最大的子节点要小,就往下移,相等不用移动
{
child = parent * 2;
if(child < H->sizee && H->Element[child] < H->Element[child+1])
child++;
if(H->Element[parent] < H->Element[child])
{
int t;
t = H->Element[parent], H->Element[parent] = H->Element[child], H->Element[child] = t;
}
else
break;
}
}
return 1;
}