堆排序是对简单选择排序的一种改进。堆排序有大顶堆(根结点最大)和小顶堆(根结点最小)之分。
基于大顶堆的完全二叉树,其核心思想为:
1)将原始序列构成一个堆。(建立初始堆)
2)交换堆的第一个元素和堆的最后一个元素的位置;
3)将移走(交换)最大值元素之后的剩余元素所构成的序列再转换为一个堆。
4)重复上述过程(2)、(3)步n-1次
问题:(1)、如何将原始序列构成一个堆;(2)如何将移走(交换)最大值元素之后的剩余元素所构成的序列再转换为一个堆;
第二个问题的算法:用adjust(k,i,n)来表示将包含n个元素的序列K中,以第i个元素作为根结点的子树调整为一个新的堆序列的过程。
void adjust(keytype k[],int i,int n) {
int i;
keytype tmp;
tmp = k[i];
j= 2*i;//j为i的左孩子结点序号
while( j <= n)
{
if(j<n && k[j]<k[j+1]) {
j++; //j为i的左右孩子中较大的孩子序号
}
if(tmp>=k[j]) {
break;//不需要再调整
}
k[j/2] = k[j];//子节点与父节点交换位置
j = 2*j; //继续向下调整
}
k[j/2] = tmp;
}
堆排序的算法:
void heapsort(keytype k[],int n) {
int i;
keytype tmp;
tmp = k[i];
j= 2*i;
for(i=n/2;i>=1;i--) {
adjust(k,i,n);//将原始序列初始化为一个堆
}
for(i=n-1;i>=1;i--) {//交换第一个和第n个元素,再将根结点向下调整
tmp = k[i+1];
k[i+1] = k[1];
k[1] = tmp;
adjust(k,1,i);
}
}
点击打开链接