您可以找本数据结构的书看看,比如清华严尉敏的《数据结构》
以下摘抄于 http://student。zjzk。cn/course_ware/data_structure/web/paixu/paixu8。4。2。1。htm 这个网站的讲解挺不错,您可以看看
1、 堆排序定义
n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):
(1) ki≤K2i且ki≤K2i 1 或(2)Ki≥K2i且ki≥K2i 1(1≤i≤ )
若将此序列所存储的向量R[1。
。n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
3、堆排序特点
堆排序(HeapSort)是一树形选择排序。
堆排序的特点是:在排序过程中,将R[l。。n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【参见二叉树的顺序存储结构】,在当前无序区中选择关键字最大(或最小)的记录。
5、堆排序
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
(1)用大根堆排序的基本思想
①先将初始文件R[1。
。n]建成一个大根堆,此堆为初始的无序区
②再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1。。n-1]和有序区R[n],且满足R[1。
。n-1]。keys≤R[n]。key
③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1。。n-1]调整为堆。然后再次将R[1。。n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1。
。n-2]和有序区R[n-1。。n],且仍满足关系R[1。。n-2]。keys≤R[n-1。。n]。keys,同样要将R[1。。n-2]调整为堆。
……
直到无序区只有一个元素为止。
(2)大根堆排序算法的基本操作:
① 初始化操作:将R[1。
。n]构造为初始堆;
② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
注意:
①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。
②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻,堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。
(3)堆排序的算法:
void HeapSort(SeqIAst R)
{ //对R[1。
。n]进行堆排序,不妨用R[0]做暂存单元
int i;
BuildHeap(R); //将R[1-n]建成初始堆
for(i=n;i>1;i--){ //对当前无序区R[1。
。i]进行堆排序,共做n-1趟。
R[0]=R[1];R[1]=R[i];R[i]=R[0]; //将堆顶和堆中最后一个记录交换
Heapify(R,1,i-1); //将R[1。
。i-1]重新调整为堆,仅有R[1]可能违反堆性质
} //endfor
} //HeapSort。
全部