一些常用的排序算法

三、      选择排序( Selection Sort 

基本思想 :每一趟在 n – i + 1 个记录中( i=1,2 ... n-1 )个记录中选取最小的那个作为第 i 个记录。

3 . 简单选择排序 (略,参考上面“基本思想”)

3 . 树形选择排序

又称“锦标赛排序”,具体步骤:首先对 n 个记录两两比较,然后再在其中的 ceil( n/2 ) 个较小者之间再两两比较,如此重复。

分析:复杂度 O ( n log n ),缺点:存储空间较多、和“最大值”进行多余的比较等缺点。

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 *Lintfirstintlast)

{

    T temp(L[first]);

 

    // 沿着记录较大的孩子结点向下筛选

    for (intj = 2 * first + 1; j <= lastj = 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(TLintlen)

{

    // L[0..len-1]建为大顶堆:

    // 从最后一个非叶子节点i起将L[i..len-1]建为大顶堆

    // 重复该过程i-1,i-2直到第个节点

    for (inti = len / 2 - 1; i >= 0; --i)

        HeapAdjust(Lilen - 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 *Lintiintmintn)

{

    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 <= mpTemp[k++] = L[l++];

    while (j <= npTemp[k++] = L[j++];

    for (k = 0; i <= ni++)

        L[i] = pTemp[k++];

 

    delete[] pTemp;

}

 

//-------------------------------------------------------------------

// L[s..t]轨并排序

//-------------------------------------------------------------------

template <typenameT>

void MSort(TLintsintt)

{

    if (s == t)

        return;

   

    int m = (s + t) / 2;

    MSort(Lsm);

    MSort(Lm + 1, t);

    Merge(Lsmt);

}

 

template <typenameT>

void MergeSort(TLintlen)

{

    MSort(L, 0, len - 1);

}

复杂度O( n log n )。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值