堆:堆是具有特殊性质的二叉树
每个结点都大于其左右儿子的的二叉树叫大顶堆
每个结点都小于其左右儿子的二叉树叫做小顶堆
堆排序图解:
给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。
首先根据该数组元素构建一个完全二叉树,得到
20和16交换后导致16不满足堆的性质,因此需重新调整
这样就得到了初始堆。
即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。
此时3位于堆顶不满堆的性质,则需调整继续调整
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int q[10005];
void HeapAdjust(int loc,int len)
{
int pos=loc; //最大值的位置(左儿子 右儿子 自己)
int left_child=2*loc;
int right_child=2*loc+1;
if(loc<=len/2) //叶子没有左右儿子 所以不用比较
{
if(left_child<=len&&q[left_child]>q[pos]) //小顶堆改小于号即可 下同
pos=left_child;
if(right_child<=len&&q[right_child]>q[pos])
pos=right_child;
if(pos!=loc) //最大值不在loc位置 交换后再比较
{
swap(q[pos],q[loc]);
HeapAdjust(pos,len);
}
}
return;
}
void heapsort(int len)
{
int i;
for(i=len/2;i>=1;i--) //初始化成为大顶堆
HeapAdjust(i,len);
for(i=len;i>=1;i--)
{
swap(q[1],q[i]); //将最大值放置于i处
HeapAdjust(1,i-1); //找前i-1个的最大值
}
return;
}
int main()
{
int n,i;
scanf("%d",&n); //输入n个数
for( i=1; i<=n; i++)
scanf("%d",&q[i]);
heapsort(n);
for(i=1; i<=n; i++)
cout<<q[i];
cout<<endl;
return 0;
}