• 内部排序->归并排序->2-路归并排序


    文字描述

      假设初始序列有n个记录,则可看成是n个有序的字序列,每个字序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,…, 如此重复,直到得到一个长度为n的有序序列为止,这种排序方法称为2-路归并排序。

    示意图

    算法分析

      2-路归并排序的时间复杂度为nlogn;

      2-路归并排序需要至少同待排序序列同等大小的辅助空间;

      与快速排序和堆排序相比,归并排序最大特点就是,它是一种稳定的排序方法。

      在一般情况下,2-路归并排序,尤其是递归形式的,很少在内部排序中使用,一般用于外部排序,因为反复的自身函数的调用,容易引起栈溢出。

    代码实现

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <math.h>
      4 /*
      5  * double log2(double x);    以2为底的对数
      6  * double ceil(double x);    取上整
      7  * double floor(double x);    取下整
      8  * double fabs(double x);    取绝对值
      9  */
     10 
     11 #define DEBUG
     12 
     13 #define EQ(a, b) ((a) == (b))
     14 #define LT(a, b) ((a) <  (b))
     15 #define LQ(a, b) ((a) <= (b))
     16 
     17 //定义顺序表中结点个数的最大值
     18 #define MAXSIZE  100
     19 //定义无穷大INF的值
     20 #define INF         1000000
     21 
     22 //定义结点中的关键字类型为int
     23 typedef int KeyType;
     24 //定义结点中除关键字外的附件信息为int
     25 typedef char InfoType;
     26 
     27 //待排序的结点的结构体
     28 typedef struct{
     29     //结点中的关键字
     30     KeyType key;
     31     //结点中的除关键字外的附加信息
     32     InfoType otherinfo;
     33 }RedType;
     34 
     35 //顺序表的结构体
     36 typedef struct{
     37     //顺序表中待排序的结点
     38     RedType r[MAXSIZE+1];
     39     //顺序表中待排序的结点个数
     40     int length;
     41 }SqList;
     42 
     43 //依次打印顺序表中结点的信息
     44 void PrintList(SqList L){
     45     int i = 0;
     46     printf("下标值:");
     47     for(i=0; i<=L.length; i++){
     48         printf("[%d] ", i);
     49     }
     50     printf("
    关键字:");
     51     for(i=0; i<=L.length; i++){
     52         if(EQ(L.r[i].key, INF)){
     53             printf(" %-3c", '-');
     54         }else{
     55             printf(" %-3d", L.r[i].key);
     56         }
     57     }
     58     printf("
    其他值:");
     59     for(i=0; i<=L.length; i++){
     60         printf(" %-3c", L.r[i].otherinfo);
     61     }
     62     printf("
    
    ");
     63     return ;
     64 }
     65 
     66 //将有序的SR[i,...,m]和SR[m+1,...,n]归并为有序的TR[i,...,n]
     67 void Merge(RedType SR[], RedType TR[], int i, int m, int n)
     68 {
     69     int j = 0, k =0;
     70     //将SR中记录由小到大地归并到TR
     71     for(j=m+1, k=i; i<=m && j<=n; ++k){
     72         if(LQ(SR[i].key, SR[j].key)){
     73             TR[k] = SR[i++];
     74         }else{
     75             TR[k] = SR[j++];
     76         }
     77     }
     78     //将剩余的SR[i,...,m]复制到TR
     79     for(; i<=m; i++){
     80         TR[k++] = SR[i];
     81     }
     82     //将剩余的SR[j,...,n]复制到TR
     83     for(; j<=n; j++){
     84         TR[k++] = SR[j];
     85     }
     86 }
     87 
     88 //将SR[s,...,t]归并排序为TR1[s,...,t]
     89 void MSort(RedType SR[], RedType TR1[], int s, int t)
     90 {
     91     if(s == t){
     92         TR1[s] = SR[s];
     93     }else{
     94         //将SR[s,...,t]平分为SR[s,...,m]和SR[m+1,...,t]
     95         int m = (s+t)/2;
     96         RedType TR2[MAXSIZE+1];
     97         //递归地将SR[s,...,m]归并为有序的TR2[s,...,m]
     98         MSort(SR, TR2, s, m);
     99         //递归地将SR[m+1,...,t]归并为有序的TR2[m+1,...,t]
    100         MSort(SR, TR2, m+1, t);
    101         //将TR2[s,...,m]和TR2[m+1,...,t]归并到TR1[s,...,t]
    102         Merge(TR2, TR1, s, m, t);
    103     }
    104 }
    105 
    106 //对顺序表L作2-路归并排序
    107 void MergeSort(SqList *L)
    108 {
    109     MSort(L->r, L->r, 1, L->length);
    110 #ifdef DEBUG
    111     printf("对该数据作2-路归并排序后:
    ");
    112     PrintList(*L);
    113 #endif
    114 }
    115 
    116 int  main(int argc, char *argv[])
    117 {
    118     if(argc < 2){
    119         return -1;
    120     }
    121     SqList L;
    122     int i = 0;
    123     for(i=1; i<argc; i++){
    124         if(i>MAXSIZE)
    125             break;
    126         L.r[i].key = atoi(argv[i]);
    127         L.r[i].otherinfo = 'a'+i-1;
    128     }
    129     L.length = (i-1);
    130     L.r[0].key = 0;
    131     L.r[0].otherinfo = '0';
    132     printf("输入数据:
    ");
    133     PrintList(L);
    134     //对顺序表L最2-路归并排序
    135     MergeSort(&L);
    136     return 0;
    137 }
    2-路归并排序

    运行

  • 相关阅读:
    如何进入闷声发大财的传统企业做数据分析工作,帮助企业做数字转型?
    做一个最好的自己,不盲目学数据分析
    sql server如何判断数据库是否存在
    c++引用深入探讨
    VirtualBox 安装ghost版windows XP
    QT透明显示文字
    CSAPP
    随机颜色的生成
    远程桌面如何传递声音的原理
    递归求解全排列
  • 原文地址:https://www.cnblogs.com/aimmiao/p/9392008.html
Copyright © 2020-2023  润新知