堆和堆排序

注:可以不用管这个想到哪儿写到哪儿的看不懂的思想和从《啊哈!算法》上抄的算法模板,只要暂时会用priority_queue就好了。

思想

堆是优先队列的实现。
一种完全二叉树。
对于最大堆,父节点的值都比子节点大;对于最小堆,父节点的值都比子节点小。
用一个数组来存树。
新增一个数,放在末尾,判断是否要进行上升操作。
将最小的数删除,将一个新的数放在堆顶,判断是否进行下沉操作。
通过这个进行堆排序,可扩展为求n个数中前k个大(小)的数,即建一个大小为k的堆进行维护。

代码

#include<bits/stdc++.h>
using namespace std;
//从大到小排序,如果从小到大,则向下调整时应记录较大结点的编号,即建立一个最大堆 
int h[101];//存放堆
int n;//堆的大小
//堆下沉
void siftdown(int i)//传入一个需要向下调成的结点编号 
{
	int t,flag=0;//标记是否需要继续调整
	//当i结点有儿子,并需要继续调整的时候执行
	while(i*2<=n && flag==0)
	{
		if(h[i]>h[i*2])
			t=i*2;
		else
			t=i;//判断其与左儿子的关系,t记录较小结点的编号 
		if(i*2+1<=n)//判断是否有右儿子
			if(h[t]>h[i*2+1])
				t=i*2+1 ;
		if(t!=i)//如果最小结点不是自己,说明子节点中有比父节点更小的数
		{
			swap(h[t],h[i]);//交换他们
			i=t;//更新i为刚刚交换的子节点编号,便于接下来的向下调整 
		} 
		else
			flag=1;
	} 
	return;
} 
//建堆 
void creat()
{
	int i;
	//从最后一个非叶节点到第1个结点依次向下调整
	for(i=n/2;i>=1;i--)
		siftdown(i);
	return; 
	
}
//堆排序
void heapsort()
{
	while(n>1)
	{
		swap(h[1],h[n]);
		n--;
		siftdown(1);
	}
	return;
 } 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int i,num;
	cin>>num;
	for(i=1;i<=num;i++)
		cin>>h[i];
	n=num;
	creat();
	heapsort();
	for(i=1;i<=num;i++)
		cout<<h[i]<<" ";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值