三、 选择排序( Selection Sort )
基本思想 :每一趟在 n – i + 1 个记录中( i=1,2 ... n-1 )个记录中选取最小的那个作为第 i 个记录。
3 . 1 简单选择排序 (略,参考上面“基本思想”)
3 . 2 树形选择排序
又称“锦标赛排序”,具体步骤:首先对 n 个记录两两比较,然后再在其中的 ceil( n/2 ) 个较小者之间再两两比较,如此重复。
分析:复杂度 O ( n log 2 n ),缺点:存储空间较多、和“最大值”进行多余的比较等缺点。
3 . 3 堆排序( Heap Sort )
堆的定义 : n 个元素序列 {K1 , K2 , ... Kn } 满足以下两者之一:
(1) Ki <= K2i 且 Ki <= K2i+1 ;
(2) Ki >= K2i 且 Ki >= K2i+1
( 其中 i = 1,2... floor(n/2) )。
其实就是一棵完全二叉树的一维数组表示 , 第 i 个记录( i 从 1 开始)的左右子树根节点分别为 2i 和 2i+1。( PS : 我们实际编程时更喜欢 i 以 0 开始, 那么就是 2i +1 和 2i + 2 )
基本步骤 :( 1 )构造一个“大顶堆”(也就是根的记录比左右子树都大);( 2 )将堆顶记录和最后一个未排序的记录(假设第 i 个)交换,将前 n-i 个记录再排为“大顶堆”;重复( 2 )直到所有记录已序。
算法伪代码:
//-------------------------------------------------------------------
// 功能: 已知L[first .. last] 中除了L[first]之外均满足堆的定义(大顶堆)
// 重新将L[first .. last] 调整为"大顶堆".
//-------------------------------------------------------------------
template <typenameT>
void HeapAdjust(T *L, intfirst, intlast)
{
T temp(L[first]);
// 沿着记录较大的孩子结点向下筛选
for (intj = 2 * first + 1; j <= last; j = 2 * j + 1)
{
// j 为较大的孩子结点的下标
if ((j < last) && (L[j] < L[j+1]))
j++;
if (temp >= L[j])
break;
L[first] = L[j];
first = j;
}
L[first] = temp;
}
//-------------------------------------------------------------------
// 功能: 堆排序
// 参数: L ---- 待排序序列; len ---- 待排序列的记录数目
//-------------------------------------------------------------------
template <typenameT>
void HeapSort(T* L, intlen)
{
// 将L[0..len-1]建为大顶堆:
// 从最后一个非叶子节点i起将L[i..len-1]建为大顶堆
// 重复该过程i-1,i-2直到第个节点
for (inti = len / 2 - 1; i >= 0; --i)
HeapAdjust(L, i, len - 1);
for (inti = len - 1; i >= 0; --i)
{
// 先将堆顶记录和当前未排序的子序列L[0..i]中最后一个记录互换
L[0] ←→ L[i];
// 再将L[0..i-1]重新调整为大顶堆
HeapAdjust(L, 0, i - 1);
}
}
复杂度O( n log n )。
四、 归并排序( Merge Sort )
2- 路归并排序基本思想 :将初始的 n 个记录看成 n 个有序的子序列,每个子序列长度为 1 ,然后两两归并,得到 ceil(n/2) 个长度为 2 或 1 的有序子序列;在两两归并, ...... 如此重复,直到得到一个长度为n 的有序序列为止。
算法代码:
//-------------------------------------------------------------------
// 将有序的L[i..m]和L[m + 1..n]归并为有序的L[i..n]
//-------------------------------------------------------------------
template <typenameT>
void Merge(T *L, inti, intm, intn)
{
T *pTemp = newT[n - i + 1];
int j = m + 1;
int k = 0;
int l = i;
for ( ; l <= m && j <= n; ++k)
{
if (L[l] <= L[j])
pTemp[k] = L[l++];
else
pTemp[k] = L[j++];
}
while (l <= m) pTemp[k++] = L[l++];
while (j <= n) pTemp[k++] = L[j++];
for (k = 0; i <= n; i++)
L[i] = pTemp[k++];
delete[] pTemp;
}
//-------------------------------------------------------------------
// 将L[s..t]轨并排序
//-------------------------------------------------------------------
template <typenameT>
void MSort(T* L, ints, intt)
{
if (s == t)
return;
int m = (s + t) / 2;
MSort(L, s, m);
MSort(L, m + 1, t);
Merge(L, s, m, t);
}
template <typenameT>
void MergeSort(T* L, intlen)
{
MSort(L, 0, len - 1);
}
复杂度O( n log n )。