排序算法

数据结构排序算法总结I

考研复习到数据结构排序这章了,这章的内容比较经典,都是一些很好的算法,将来很可能会用得到,总结一下,加深一下印象。

             文章篇幅有点大,请点击查看更多,下面是跳转链接:

              一、插入排序      1直接插入排序      2折半插入排序      3希尔排序

              二、交换排序      1冒泡排序           2快速排序     

              三、选择排序      1简单选择排序      2堆排序     

               四、归并排序     

              五、基数排序    

       一、插入排序

             1)直接插入排序     算法演示

              时间复杂度:平均情况—O(n2)     最坏情况—O(n2)     辅助空间:O(1)      稳定性:稳定

复制到剪贴板折叠C 代码

  1. void InsertSort(SqList &L) {     
  2.   // 对顺序表L作直接插入排序。   
  3.   int i,j;   
  4.   for (i=2; i<=L.length; ++i)   
  5.     if (LT(L.r[i].key, L.r[i-1].key)) {   
  6.       // "<"时,需将L.r[i]插入有序子表   
  7.        L.r[0] = L.r[i];                 // 复制为哨兵   
  8.       for (j=i-1;   LT(L.r[0].key, L.r[j].key);   --j)   
  9.          L.r[j+1] = L.r[j];             // 记录后移   
  10.        L.r[j+1] = L.r[0];               // 插入到正确位置   
  11.      }   
  12. } // InsertSort   

             2)折半插入排序

              时间复杂度:平均情况—O(n2)     稳定性:稳定

复制到剪贴板折叠C 代码

  1. void BInsertSort(SqList &L) {     
  2.   // 对顺序表L作折半插入排序。   
  3.   int i,j,high,low,m;   
  4.   for (i=2; i<=L.length; ++i) {   
  5.      L.r[0] = L.r[i];       // L.r[i]暂存到L.r[0]   
  6.      low = 1;    high = i-1;   
  7.     while (low<=high) {    // r[low..high]中折半查找有序插入的位置   
  8.        m = (low+high)/2;                            // 折半   
  9.       if (LT(L.r[0].key, L.r[m].key)) high = m-1;  // 插入点在低半区   
  10.       else   low = m+1;                             // 插入点在高半区   
  11.      }   
  12.     for (j=i-1; j>=high+1; --j) L.r[j+1] = L.r[j];  // 记录后移   
  13.      L.r[high+1] = L.r[0];                           // 插入   
  14.    }   
  15. } // BInsertSort   

             3)希尔排序 算法演示

              时间复杂度:理想情况—O(nlog2n)      最坏情况—O(n2)     稳定性:不稳定

复制到剪贴板折叠C 代码

  1. void ShellInsert(SqList &L, int dk) {     
  2.   // 对顺序表L作一趟希尔插入排序。本算法对算法10.1作了以下修改:   
  3.   //      1. 前后记录位置的增量是dk,而不是1   
  4.   //      2. r[0]只是暂存单元,不是哨兵。当j<=0时,插入位置已找到。   
  5.   int i,j;   
  6.   for (i=dk+1; i<=L.length; ++i)   
  7.     if (LT(L.r[i].key, L.r[i-dk].key)) { // 需将L.r[i]插入有序增量子表   
  8.        L.r[0] = L.r[i];                   // 暂存在L.r[0]   
  9.       for (j=i-dk; j>0 && LT(L.r[0].key, L.r[j].key); j-=dk)   
  10.          L.r[j+dk] = L.r[j];              // 记录后移,查找插入位置   
  11.        L.r[j+dk] = L.r[0];                // 插入   
  12.      }   
  13. } // ShellInsert   
  14.   
  15.   
  16. void ShellSort(SqList &L, int dlta[], int t) {  
  17.    // 按增量序列dlta[0..t-1]对顺序表L作希尔排序。   
  18.    for (int k=0; k<t; ++k)   
  19.        ShellInsert(L, dlta[k]);  // 一趟增量为dlta[k]的插入排序   
  20. } // ShellSort   

        二、交换排序

             1)冒泡排序 算法演示

              时间复杂度:平均情况—O(n2)     最坏情况—O(n2)     辅助空间:O(1)      稳定性:稳定

复制到剪贴板折叠C 代码

  1. void BubbleSort(SeqList R) {   
  2. int ij;   
  3. Boolean exchange; //交换标志   
  4. for(i=1;i<n;i++){ //最多做n-1趟排序   
  5.       exchange=FALSE; //本趟排序开始前,交换标志应为假   
  6.      for(j=n-1;j>=i;j--) //对当前无序区R[i..n]自下向上扫描   
  7.           if(R[j+1].key<R[j].key){//交换记录   
  8.                R[0]=R[j+1]; //R[0]不是哨兵,仅做暂存单元   
  9.                R[j+1]=R[j];   
  10.                R[j]=R[0];   
  11.                exchange=TRUE; //发生了交换,故将交换标志置为真   
  12.            }   
  13.           if(!exchange) //本趟排序未发生交换,提前终止算法   
  14.           return;   
  15. } //endfor(外循环)   
  16. } //BubbleSort   

             2)快速排序 算法演示

              时间复杂度:平均情况—O(nlog2n)     最坏情况—O(n2)     辅助空间:O(log2n)      稳定性:不稳定

复制到剪贴板折叠C 代码

  1. int Partition(SqList &L, int low, int high) {     
  2. // 交换顺序表L中子序列L.r[low..high]的记录,使枢轴记录到位,       
  3.    // 并返回其所在位置,此时,在它之前(后)的记录均不大(小)于它       
  4.     KeyType pivotkey;       
  5.     RedType temp;       
  6.     pivotkey = L.r[low].key;     // 用子表的第一个记录作枢轴记录       
  7.    while (low<high) {           // 从表的两端交替地向中间扫描       
  8.       while (low<high && L.r[high].key>=pivotkey) --high;       
  9.        temp=L.r[low];       
  10.        L.r[low]=L.r[high];       
  11.        L.r[high]=temp;           // 将比枢轴记录小的记录交换到低端       
  12.       while (low<high && L.r[low].key<=pivotkey) ++low;       
  13.        temp=L.r[low];       
  14.        L.r[low]=L.r[high];       
  15.        L.r[high]=temp;           // 将比枢轴记录大的记录交换到高端       
  16.     }       
  17.    return low;                  // 返回枢轴所在位置       
  18. } // Partition       
  19.       
  20. int Partition(SqList &L, int low, int high) {      
  21. // 交换顺序表L中子序列L.r[low..high]的记录,使枢轴记录到位,       
  22.    // 并返回其所在位置,此时,在它之前(后)的记录均不大(小)于它       
  23.     KeyType pivotkey;       
  24.     L.r[0] = L.r[low];            // 用子表的第一个记录作枢轴记录       
  25.     pivotkey = L.r[low].key;      // 枢轴记录关键字       
  26.    while (low<high) {            // 从表的两端交替地向中间扫描       
  27.       while (low<high && L.r[high].key>=pivotkey) --high;       
  28.        L.r[low] = L.r[high];      // 将比枢轴记录小的记录移到低端       
  29.       while (low<high && L.r[low].key<=pivotkey) ++low;       
  30.        L.r[high] = L.r[low];      // 将比枢轴记录大的记录移到高端       
  31.     }       
  32.     L.r[low] = L.r[0];            // 枢轴记录到位       
  33.    return low;                   // 返回枢轴位置       
  34. } // Partition       
  35.       
  36.       
  37. void QSort(SqList &L, int low, int high) {         
  38.   // 对顺序表L中的子序列L.r[low..high]进行快速排序       
  39.   int pivotloc;       
  40.   if (low < high) {                      // 长度大于1       
  41.      pivotloc = Partition(L, low, high);  // L.r[low..high]一分为二       
  42.      QSort(L, low, pivotloc-1); // 对低子表递归排序,pivotloc是枢轴位置       
  43.      QSort(L, pivotloc+1, high);          // 对高子表递归排序       
  44.    }       
  45. } // QSort   
  46.   
  47. void QuickSort(SqList &L) {  // 算法10.8   
  48.    // 对顺序表L进行快速排序   
  49.     QSort(L, 1, L.length);   
  50. } // QuickSort   

 三、选择排序

             1)简单选择排序 算法演示

              时间复杂度:平均情况—O(n2)     最坏情况—O(n2)     辅助空间:O(1)      稳定性:不稳定

复制到剪贴板折叠C 代码

  1. void SelectSort(SqList &L) {     
  2.   // 对顺序表L作简单选择排序。   
  3.   int i,j;   
  4.   for (i=1; i<L.length; ++i) { // 选择第i小的记录,并交换到位   
  5.      j = SelectMinKey(L, i);  // L.r[i..L.length]中选择key最小的记录   
  6.     if (i!=j) {                // L.r[i]←→L.r[j];    与第i个记录交换   
  7.        RedType temp;   
  8.        temp=L.r[i];   
  9.        L.r[i]=L.r[j];   
  10.        L.r[j]=temp;       
  11.      }   
  12.    }   
  13. } // SelectSort   

             2)堆排序 算法演示

              时间复杂度:平均情况—O(nlog2n)     最坏情况—O(nlog2n)     辅助空间:O(1)      稳定性:不稳定

复制到剪贴板折叠C 代码

  1. void HeapAdjust(HeapType &H, int s, int m) {     
  2.   // 已知H.r[s..m]中记录的关键字除H.r[s].key之外均满足堆的定义,   
  3.   // 本函数调整H.r[s]的关键字,使H.r[s..m]成为一个大顶堆   
  4.   // (对其中记录的关键字而言)   
  5.   int j;   
  6.    RedType rc;   
  7.    rc = H.r[s];   
  8.   for (j=2*s; j<=m; j*=2) {   // 沿key较大的孩子结点向下筛选   
  9.     if (j<m && H.r[j].key<H.r[j+1].key) ++j; // jkey较大的记录的下标   
  10.     if (rc.key >= H.r[j].key) break;         // rc应插入在位置s   
  11.      H.r[s] = H.r[j];   s = j;   
  12.    }   
  13.    H.r[s] = rc;  // 插入   
  14. } // HeapAdjust   
  15.   
  16. void HeapSort(HeapType &H) {     
  17.    // 对顺序表H进行堆排序。   
  18.    int i;   
  19.     RedType temp;   
  20.    for (i=H.length/2; i>0; --i)  // H.r[1..H.length]建成大顶堆   
  21.        HeapAdjust ( H, i, H.length );   
  22.       for (i=H.length; i>1; --i) {   
  23.           temp=H.r[i];   
  24.           H.r[i]=H.r[1];   
  25.           H.r[1]=temp;  // 将堆顶记录和当前未经排序子序列Hr[1..i]   
  26.                        // 最后一个记录相互交换   
  27.           HeapAdjust(H, 1, i-1);  // H.r[1..i-1] 重新调整为大顶堆   
  28.        }   
  29. } // HeapSort   

        四、归并排序

             1)归并排序 算法演示

              时间复杂度:平均情况—O(nlog2n)      最坏情况—O(nlog2n)      辅助空间:O(n)      稳定性:稳定

复制到剪贴板折叠C 代码

  1. void Merge (RedType SR[], RedType TR[], int i, int m, int n) {   
  2.    // 将有序的SR[i..m]SR[m+1..n]归并为有序的TR[i..n]   
  3.    int j,k;   
  4.    for (j=m+1, k=i;   i<=m && j<=n;   ++k) {      
  5.       // SR中记录由小到大地并入TR   
  6.       if LQ(SR[i].key,SR[j].key) TR[k] = SR[i++];   
  7.       else TR[k] = SR[j++];   
  8.     }   
  9.    if (i<=m)  // TR[k..n] = SR[i..m];   将剩余的SR[i..m]复制到TR   
  10.       while (k<=n && i<=m) TR[k++]=SR[i++];   
  11.    if (j<=n)  // 将剩余的SR[j..n]复制到TR   
  12.       while (k<=n &&j <=n) TR[k++]=SR[j++];   
  13. } // Merge   
  14.   
  15. void MSort(RedType SR[], RedType TR1[], int s, int t) {   
  16.    // SR[s..t]归并排序为TR1[s..t]   
  17.    int m;   
  18.     RedType TR2[20];   
  19.    if (s==t) TR1[t] = SR[s];   
  20.    else {   
  21.        m=(s+t)/2;            // SR[s..t]平分为SR[s..m]SR[m+1..t]   
  22.        MSort(SR,TR2,s,m);    // 递归地将SR[s..m]归并为有序的TR2[s..m]   
  23.        MSort(SR,TR2,m+1,t);  // SR[m+1..t]归并为有序的TR2[m+1..t]   
  24.        Merge(TR2,TR1,s,m,t); // TR2[s..m]TR2[m+1..t]归并到TR1[s..t]   
  25.     }   
  26. } // MSort   
  27.   
  28. void MergeSort(SqList &L) {     
  29.   // 对顺序表L作归并排序。   
  30.    MSort(L.r, L.r, 1, L.length);   
  31. } // MergeSort   

        五、基数排序

             1)基数排序 算法演示

时间复杂度:平均情况—O(d(n+rd))      最坏情况—O(d(n+rd))      辅助空间:O(rd)      稳定性:稳定

复制到剪贴板折叠C 代码

  1. void Distribute(SLList &L, int i, ArrType &f, ArrType &e) {     
  2.   // 静态链表Lr域中记录已按(keys[0],...,keys[i-1])有序,   
  3.   // 本算法按第i个关键字keys[i]建立RADIX个子表,   
  4.   // 使同一子表中记录的keys[i]相同。f[0..RADIX-1]e[0..RADIX-1]   
  5.   // 分别指向各子表中第一个和最后一个记录。   
  6.   int j, p;   
  7.   for (j=0; j<RADIX; ++j) f[j] = 0;     // 各子表初始化为空表   
  8.   for (p=L.r[0].next;   p;   p=L.r[p].next) {   
  9.      j = L.r[p].keys[i]-'0';  // 将记录中第i个关键字映射到[0..RADIX-1]   
  10.     if (!f[j]) f[j] = p;   
  11.     else L.r[e[j]].next = p;   
  12.      e[j] = p;                // p所指的结点插入第j个子表中   
  13.    }   
  14. } // Distribute   
  15.   
  16. void Collect(SLList &L, int i, ArrType f, ArrType e) {     
  17.   // 本算法按keys[i]自小至大地将f[0..RADIX-1]所指各子表依次链接成   
  18.   // 一个链表,e[0..RADIX-1]为各子表的尾指针   
  19.   int j,t;   
  20.   for (j=0; !f[j]; j++);  // 找第一个非空子表,succ为求后继函数: ++   
  21.    L.r[0].next = f[j];  // L.r[0].next指向第一个非空子表中第一个结点   
  22.    t = e[j];   
  23.   while (j<RADIX) {   
  24.     for (j=j+1; j<RADIX && !f[j]; j++);       // 找下一个非空子表   
  25.     if (j<RADIX) // 链接两个非空子表   
  26.        { L.r[t].next = f[j];   t = e[j]; }   
  27.    }   
  28.    L.r[t].next = 0;   // t指向最后一个非空子表中的最后一个结点   
  29. } // Collect   
  30.   
  31. void RadixSort(SLList &L) {     
  32.    // L是采用静态链表表示的顺序表。   
  33.    // L作基数排序,使得L成为按关键字自小到大的有序静态链表,   
  34.    // L.r[0]为头结点。   
  35.    int i;   
  36.     ArrType f, e;   
  37.    for (i=1; i<L.recnum; ++i) L.r[i-1].next = i;   
  38.     L.r[L.recnum].next = 0;     // L改造为静态链表   
  39.    for (i=0; i<L.keynum; ++i) {     
  40.       // 按最低位优先依次对各关键字进行分配和收集   
  41.        Distribute(L, i, f, e);    // i趟分配   
  42.        Collect(L, i, f, e);       // i趟收集   
  43.        print_SLList2(L, i);   
  44.     }   
  45. } // RadixSort 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值