前言
本文采用结构体重载比较运算符的方式进行大根堆的建立,算法逻辑类似 S T L STL STL的 p r i o r i t y _ q u e u e priority\_queue priority_queue。
结构体
堆本身就是一颗完全二叉树,所以本身用数组存储就行。
int heap[N];
输入堆
for(int i=1;i<=n;i++} cin>>heap[i];
向上调整堆
建堆后,从第一个非叶结点开始向前递减循环,依次比较堆是否比最大的孩子小,是的话则交换。
void adjustUp(){
for(int i=len/2;i>=1;i--){
int l=2*i;//默认左孩子
if(l+1<=len&&heap[l+1]>heap[l] l++;//最大为右孩子情况
if(heap[m]>heap[i] swap(heap[m],heap[i];//交换m,i
}
}
删除堆顶元素
在堆中,删除堆顶元素实际上就是交换堆顶和最后一个元素后让堆长度减 1 1 1。然后从堆顶 i = 1 i=1 i=1开始向下调整:
- 找到 i i i最大的孩子结点编号 i c ic ic
- 比较 i i i与 i c ic ic值的大小,若不符合堆得定义则交换
- 令 i = i c i=ic i=ic,继续第1步直到 i i i为叶子结点
void deleteHeap(){
//交换堆顶和尾部元素
cout<<heap[1]<<' ';
swap(heap[1],heap[len]);
len--;//长度-1
int i=1;//分支选择i
while(2*i<=len){
int j=2*i+1;//进入下一层
if(j>len || heap[j-1]>heap[j]) j--;
if(heap[i]<heap[j] swap(heap[i],heap[j]);
i=j;
}
}
优先队列方式输出
有输入当然也有输出
void input(){
while(len!=0){
deleteHeap();
}
}
STL堆
在STL库当中,自然也是有堆的相关函数的,位于 < a l g o r i t h m > <algorithm> <algorithm>。- heap没有对应容器,STL中只有相关算法:
-
make_heap 建堆
-
push_heap 入堆
-
pop_heap 出堆
-
sort_heap 排序堆
他们的参数如下所示:
void make_heap(first,last,comp)
void push_heap(first,last,comp)
void pop_heap(first,last,comp)
void sort_heap(first,last,comp)
各含义如下:
first 堆起始位置 num+i s.begin()
last 堆末尾位置+1 num+n s.end()
comp 自定义比较函数,不填默认大顶堆
除了push_heap,全都是[first,last)
push_heap将last加入堆[first,last-1)
入堆
入堆很简单,输入数组第i个后,直接采取区间的方式调用函数即可。
cin>>n;//入堆n个元素
for(int i=0;i<n;i++){
int p;
cin>>num[i];
push_heap(num,num+i);//入堆
}
出堆
出堆的话,因为大小一直在改变,所以循环要逆序,堆顶是数组 0 0 0的位置,每次输出后要调用 p o p h e a p pop_heap popheap重新调整堆。
for(int i=n+1;i>=0;i--){//输出之后排堆的元素少1
cout<<num[0]<<' ';
pop_heap(num,num+i);//出堆
}