【C++】堆排序

215 阅读1分钟

「这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战」。

前言

本文采用结构体重载比较运算符的方式进行大根堆的建立,算法逻辑类似STLSTLpriority_queuepriority\_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
	}
}

删除堆顶元素

在堆中,删除堆顶元素实际上就是交换堆顶和最后一个元素后让堆长度减11。然后从堆顶i=1i=1开始向下调整:

  1. 找到ii最大的孩子结点编号icic
  2. 比较iiicic值的大小,若不符合堆得定义则交换
  3. i=ici=ic,继续第1步直到ii为叶子结点
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库当中,自然也是有堆的相关函数的,位于<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);//入堆 
}

出堆

出堆的话,因为大小一直在改变,所以循环要逆序,堆顶是数组00的位置,每次输出后要调用popheappop_heap重新调整堆。

for(int i=n+1;i>=0;i--){//输出之后排堆的元素少1 
	cout<<num[0]<<' ';
	pop_heap(num,num+i);//出堆 
}