|
发表于 2017-8-6 16:18:50
|
显示全部楼层
一个元素的堆调整算法:
//已知H.R[s...m]除H.R[s]之外,均满足堆的定义,本函数只是将H.R[s]放到已经是堆的堆中
void HeapAdjust (SqList& H, int s, int m) ∥将(H.R[s]……H.R[m])调整成大根堆∥
{
rc=H.R[s]; ∥暂存H.R[s]∥
for(j=2*s;jL.R[j].key)
break;//说明H.R[s]已经比当前堆中的所有元素大,已经是堆了,不需要调整了
L.R[s]=L.R[j]; ∥把最大的放到根结点
s=j; ∥把s与j交换,使得s与下层的堆比较
}
L.R[s]=rc; ∥最初的根回归∥
}
void Heapsort (SqList& H) ∥ 堆排序算法∥
{
//初始建堆
for (i=L.len/2; i>=1; i--) //从完全二叉树的最后一个非叶子结点开始
HeapAdjust (L,i,L.len); ∥调整(R[i]……R[n])为堆∥
//每次取下根(最大的元素)所谓的取下,只是放到数组最后,改变一下数组的下界
for (i=L.len;i>=2;i--) ∥总共摘n-1次∥
{ temp=F.R[1]; ∥根与当前最后一个结点互换∥
F.R[1]=F.R[i];
F.R[i]=temp;
HeapAdjust (L ,1,i-1); ∥把最后一个元素调整到合适的位置∥
}
}
二路归并排序:(稳定的,时间复杂度O(nlogn)又稳定又效率高,但需要辅助空间TR[1....n]
二路归并得核心操作是将一维数组中前后相邻的两个有序序列归并为一个有序序列
(注意这就是线型表中我们常考的那个,两个有序链表合成一个新的有序表)
算法描述如下:
void Merge(RcdType SR[],RcdType&TR[],int i,int m,int n)
//将有序的SR[i...m]和SR[m+1....n]归并为有序的TR[i....n]
{
for(j=m+1,k=i; i<=m&&j<=n; ++k) //谁小就先将谁放进TR
{ if(SR[i].key<=SR[j].key)
TR[k]=SR[i++];
else
TR[k]=SR[j++];
}
if(i<=m) //将剩余的SR 直接放到TR
TR[k....n]=SR[i...m];
if(j<=n) //将剩余的SR 直接放到TR
TR[k...n]=SR[j....n];
}
void MSort(RcdType SR[], RcdType&TR1[], int s, int t)
{ //将SR[s...t]归并排序为TR1[s...t]
if(s= =t) //只有一个元素
TR1[s]=SR[s];
else
{
m=(s+t)/2;//将SR[]平分为两半
MSort(SR, TR2, s, m);
MSort(SR, TR2, m+1, t);
Merge(TR2, TR1, s, m, t);
}
}
|
|