• 内部排序->插入排序->希尔排序


    文字描述

      希尔排序又称缩小增量排序,也属于插入排序类,但在时间效率上较之前的插入排序有较大的改进。

      从之前的直接插入排序的分析得知,时间复杂度为n*n, 有如下两个特点:

      (1)如果待排序记录本身就是“正序”时, 其时间复杂度可减少为n。

      (2)当待排序记录数很小时,直接插入排序的效率也比较高; 

      希尔排序正是从这两点分析出发对直接插入排序进行了改进。它的基本思想是:先将整个待排记录序列分割成为若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序“时,再对全体记录进行一次直接插入排序。

    示意图

    算法分析

      希尔排序的空间复杂度是所取增量数组的个数加1。

      希尔排序的时间复杂度分析是一个复杂的问题,因为它的时间是所取”增量”序列的函数,这涉及一些数学上尚未解决的难题。但是在大量的前人做的实验基础上推出:当n在某个特定范围内,希尔排序所需的比较和移动次数均约为n^(1.3), 当n无穷大时,可减少到n(log2n)^2。

      增量序列可以有各种取法,但是需注意:应使增量序列中的值没有除1之外的公因子,并且最后一个增量值必须等于1。

      希尔排序是不稳定的

    代码实现

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #define DEBUG
      5 
      6 #define EQ(a, b) ((a) == (b))
      7 #define LT(a, b) ((a) <  (b))
      8 #define LQ(a, b) ((a) <= (b))
      9 
     10 #define MAXSIZE 20
     11 typedef int KeyType;
     12 typedef int InfoType;
     13 typedef struct{
     14     KeyType key;
     15     InfoType otherinfo;
     16 }RedType;
     17 
     18 typedef struct{
     19     RedType r[MAXSIZE+1];
     20     int length;
     21 }SqList;
     22 
     23 //依次打印顺序表L中的下标和关键字
     24 void PrintList(SqList L){
     25     int i = 0;
     26     printf("下标值:");
     27     for(i=0; i<=L.length; i++){
     28         printf("[%d] ", i);
     29     }
     30     printf("
    关键字:");
     31     for(i=0; i<=L.length; i++){
     32         printf(" %-3d", L.r[i].key);
     33     }
     34     printf("
    其他值:");
     35     for(i=0; i<=L.length; i++){
     36         printf(" %-3c", L.r[i].otherinfo);
     37     }
     38     printf("
    
    ");
     39     return ;
     40 }
     41 
     42 /*
     43  *对顺序表L作一趟希尔插入排序。本算法和一趟直接插入
     44  *排序相比,作了以下修改:
     45  * 1。前后记录位置的增量为dk, 而不是1
     46  * 2。r[0]只是暂存单元,不是哨兵
     47  */
     48 void ShellInsert(SqList *L, int dk)
     49 {
     50     int i = 0, j = 0;
     51     for(i=dk+1; i<=L->length; ++i){
     52         //需将L->r[i]插入有序增量子表
     53         if(LT(L->r[i].key, L->r[i-dk].key)){
     54             //暂存在L->r[0]
     55             L->r[0] = L->r[i];
     56             for(j=i-dk; j>0&&LT(L->r[0].key, L->r[j].key); j-=dk){
     57                 //记录后移,找插入位置
     58                 L->r[j+dk] = L->r[j];
     59             }
     60             //插入位置找到,插入数据
     61             L->r[j+dk] = L->r[0];
     62         }
     63     }
     64 }
     65 
     66 //按照增量序列dlta[0..t-1]对顺序表L作希尔排序
     67 void ShellSort(SqList *L, int dlta[], int t)
     68 {
     69 #ifdef DEBUG
     70     printf("输入数组:
    ");
     71     PrintList(*L);
     72 #endif
     73     int k = 0;
     74     for(k=0; k<t; k++){
     75         //一趟增量为dlta[k]的插入排序
     76         ShellInsert(L, dlta[k]);
     77 #ifdef DEBUG
     78         printf("第%d趟增量%d希尔排序后:
    ", k, dlta[k]);
     79         PrintList(*L);
     80 #endif
     81     }
     82 }
     83 
     84 int  main(int argc, char *argv[])
     85 {
     86     if(argc < 2){
     87         return -1;
     88     }
     89     SqList L;
     90     int i = 0;
     91     for(i=1; i<argc; i++){
     92         if(i>MAXSIZE)
     93             break;
     94         L.r[i].key = atoi(argv[i]);
     95         L.r[i].otherinfo = 'a'+i-1;
     96     }
     97     L.length = (i-1);
     98     L.r[0].key = 0;
     99     L.r[0].otherinfo = '0';
    100     //希尔排序的增量 依次取9 5 3 1
    101     int dlta[4] = {9,5,3,1};
    102     //调用希尔排序算法
    103     ShellSort(&L, dlta, 4);
    104     return 0;
    105 }
    希尔排序

    运行

  • 相关阅读:
    TCP粘包,产生的原因以及解决方案
    php判断变量是否为正整数
    php函数trim中文编码问题解决
    win10设置开机自动启动vagrant虚拟机
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
    git push 时 fatal: Unable to create 'D:/phpStudy/WWW/green_tree/.git/index.lock': File exists.解决办法
    git push 提示 Everything up-to-date
    Allowed memory size of 134217728 bytes exhausted (tried to allocate 2 bytes)
    访问远程mysql数据库,出现报错,显示“1130
    改变网页选中文本的颜色
  • 原文地址:https://www.cnblogs.com/aimmiao/p/9367612.html
Copyright © 2020-2023  润新知