【题目】 求堆排序算法
【算法分析】
1. 基本思想:
堆排序是一树形选择排序,在排序过程中,将 R[1..N]看成是一颗完全二叉树的顺序存
储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。
2. 堆的定义:
N 个元素的序列 K1,K2,K3,...,Kn.称为堆,当且仅当该序列满足特性:
Ki≤K2i
Ki ≤K2i+1(1≤ I≤ [N/2])
3. 排序过程:
堆排序正是利用小根堆(或大根堆)来选取当前无序区中关键字小(或最大)的记录实现排
序的。我们不妨利用大根堆来排序。每一趟排序的基本操作是:将当前无序区调整为一个大
根堆,选取关键字最大的堆顶记录,将它和无序区中的最后一个记录交换。这样,正好和直
接选择排序相反,有序区是在原记录区的尾部形成并逐步向前扩大到整个记录区。
【算法实现】
tpedef SqList HeapType;//堆采用顺序表存储表示
void HeadAdjust(HeadType &H,int s,int m){
rc=H.r[s];
for(j=2*slj<=m;j*=2){
if(j
0;--i){
HeadAdjust(H,I,H.length);
For(i=H.length;i>1’—i){
H.r[1]>H.r[i];
HeadAdjust(H,1,i-1);
}
}
【源代码】
void HeapAdjust(SqList &list,int s,int m)
{
//前提条件:list 中除 list.key[s]之外均满足堆的定义
//目的 :重新调整 list,使其满足大根堆的条件
KeyType rc = list.key[s];
for(int j=2*s; j<=m; j*=2){
if(jj++;
if(rc > list.key[j])
break;
list.key[s] = list.key[j];
s = j;
}
list.key[s] = rc;
}
void HeapSort(SqList &list)
{
KeyType temp;
for(int i = list.Length/2; i>0; i--)
HeapAdjust(list,i,list.Length);
for(i = list.Length; i>1; --i){
temp = list.key[1];
list.key[1] = list.key[i];
list.key[i] = temp;
HeapAdjust(list,1,i-1);
}
//将 list 建成大根堆,从表后往前调整
//每次将大根堆的第一个元素(即值最大)
//取出来放在末尾位置上(撇开已经排好的序列)
//重新调整 list 为大根堆
}
【算法分析】
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调
用 Heapify 实现的。
堆排序的最坏时间复杂度为 O(nlgn)。堆排序的平均性能较接近于最坏性能。
由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。
堆排序是就地排序,辅助空间为 O(1),
它是不稳定的排序方法。