堆:堆是具有特殊性质的二叉树
每个结点都大于其左右儿子的的二叉树叫大顶堆
每个结点都小于其左右儿子的二叉树叫做小顶堆
堆排序图解:
给定一个整形数组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; }
时间: 2024-08-08 01:45:01