• [数据结构]希尔排序


    一、问题描述

    内部排序是一件具有重大意义的问题,许多项目的实现中都需要用到排序。

    我们知道,排序的算法有许多种,每种排序算法的时间复杂度和空间复杂度不尽相同。在解决实际问题时,往往需要根据实际需要选择排序算法。

    本实验重点介绍希尔排序的算法实现及其原理,简要说明与其相关的直接排序算法,并讨论希尔排序中步长的选择对排序速度的影响。

    二、数据结构——顺序结构

    本实验重点在算法实现上,数据结构的思想被弱化了。在排序过程中,由于维护序关系的需要,要有交换的操作,这就破坏了ADT的物理位置的相邻反映逻辑的依次的性质,可以说这里的顺序结构只是一个二次结构。因此,本实验不对此作过多说明。

    三、算法的设计和实现

    (1)直接排序(直接插入排序)

    a)简述

    以不降序排序为例,直接排序在每一轮排序中,找到出现的第一个破坏不降序性质的元素,将其值保存至a[0]处,然后向前扫,直到找到小于或等于a[0]的元素a[i],然后将a[0]插入到a[i]之后,后面的元素依次后移一位。重复上述过程,由循环不变式可知,最后得到的序列是保持不降序性质的。

    可以看出,直接排序是一种基于插入的排序算法。算法的时间复杂度为O(n^2)。值得注意的是,直接排序只涉及到两个相邻数的交换,所以是稳定的。

    b)例子:空白处的表示不改变,当前循环将不会访问到。

    a[0] 49 38 65 97 76 13 27
    38 38 49          
    76 38 49 65 76 97    
    13 13 38 49 65 76 97  
    27 13 27 38 49 65 76 97

    (1)希尔排序

    a)简述

    希尔排序是直接排序的一个升级版。以步长将待排序的序列划分成几个部分,将每个部分进行排序,使得整个序列粗有序,从而减少序列的移动次数,减小时间复杂度。

    b)算法描述

    首先枚举步长gap,以步长将待排序的序列分为gap个子序列,对每个子序列进行直接排序。步长从粗到细,最后一次步长为1。步长的选取直接关系到希尔排序的时间效率,一般来说,为了尽量避免重复计算,选取的步长要互质;至于更系统的讨论将在下面给出。

    c)例子

    步长 49 38 65 97 76 13 27 49 55 4
    5 13 27 49 55 4 49 38 65 97 76
    3 13 4 49 38 27 49 55 65 97 76
    1 4 13 27 38 49 49 55 65 76 97

    d)可以看出,希尔排序不仅基于插入,还有大跨度交换的操作,所以希尔排序是不稳定的。

    四、预期结果和实验中的问题

    1、预期结果

    程序能够正确地将一个序列按照不递减的顺序排序。下图为一个例子。

    2、实验中的问题及思考

    (1)问题:希尔排序的步长选择对算法效率的影响。

    (2)解答:这是一个公开问题,似乎还没有一个特别完美的解释。维基百科上有相关的说明。https://en.wikipedia.org/wiki/Shellsort

    附:c++源代码:

     1 /*
     2 项目:shell sort
     3 作者:张译尹
     4 */
     5 #include <iostream>
     6 #include <cstdio>
     7 #include <cstring>
     8 
     9 using namespace std;
    10 #define MaxN 120
    11 
    12 int gap[200]; //步长 2^k+1 第一项改为1 
    13 int n;
    14 
    15 template <class T> class My_list
    16 {
    17 private:
    18     T Elem[MaxN]; //待排序的元素 
    19     int Len; //元素个数 
    20 public:
    21     void Init()
    22     {
    23         memset(Elem, 0, sizeof(Elem));
    24         Len = 0;
    25     }
    26     void Insert_back(T x)
    27     {
    28         Elem[++Len] = x;
    29     }
    30     void Print()
    31     {
    32         int i;
    33         for(i = 1; i < Len; i++)
    34             printf("%d ", Elem[i]);
    35         printf("%d
    ", Elem[i]);
    36     }
    37     int GetLen()
    38     {
    39         return Len;
    40     }
    41     void ShellSort()
    42     {
    43         int i, j, k;
    44         for(k = gap[0]; k >= 1; k--)
    45         {
    46             for(i = gap[k]; i <= Len; i++)
    47             {
    48                 Elem[0] = Elem[i];
    49                 
    50                 //把比当前元素大的都往后移动 
    51                 for(j = i - gap[k]; j >= 0 && Elem[0] < Elem[j]; j -= gap[k])
    52                     Elem[j + gap[k]] = Elem[j];
    53                 Elem[j + gap[k]] = Elem[0];
    54             }
    55         }
    56     }
    57 };
    58 
    59 void Read(My_list <int> &L)
    60 {
    61     int i, x;
    62     L.Init();
    63     printf("请输入需要排序的数的个数。
    ");
    64     scanf("%d", &n);
    65     printf("请输入需要排序的数列。
    "); 
    66     for(i = 1; i <= n; i++)
    67     {
    68         scanf("%d", &x);
    69         L.Insert_back(x); //把x插入到最后 
    70     }
    71 }
    72 
    73 void Pre_gap(My_list <int> &L)
    74 {
    75     int i, tmp = 2, n = L.GetLen();
    76     for(i = 2; ; i++)
    77     {
    78         tmp = ((tmp - 1) << 1) + 1;
    79         gap[i] = tmp;
    80         if(tmp >= n / 2)
    81             break;
    82     }
    83     gap[1] = 1;
    84     gap[0] = i;
    85 }
    86 
    87 int main()
    88 {
    89     int GapNum;
    90     My_list <int> L;
    91     Read(L);
    92     Pre_gap(L);
    93     L.ShellSort();
    94     printf("升序排序后的数列:
    ");
    95     L.Print();
    96     return 0;
    97 }
    View Code
  • 相关阅读:
    POJ
    hdu 5652
    CodeForces
    #6285. 数列分块入门 9
    #6284. 数列分块入门 8
    #6283. 数列分块入门 7
    #6282. 数列分块入门 6
    #6280. 数列分块入门 4 #6281. 数列分块入门 5
    #6278. 数列分块入门 2和#6278. 数列分块入门 3
    spark-sklearn TypeError: 'JavaPackage' object is not callable
  • 原文地址:https://www.cnblogs.com/CQBZOIer-zyy/p/5185410.html
Copyright © 2020-2023  润新知