【数据结构】八大排序之希尔排序算法

举报
修修修也 发表于 2024/09/30 16:36:31 2024/09/30
【摘要】 🦄个人主页:修修修也 🎏所属专栏:数据 结 构 ⚙️操作环境:Visual Studio 2022​编辑一.优化直接插入排序算法我们在之前对直接插入排序算法的优化部分通过对直接插入排序的分析可以得到一个结论,即:       进行直接插入排序的数组,如果越接近局部有序,则后续进行直接插入排序算法时其时间复杂度就会越低.       所谓基本有序,就是指小的关键字基本在前面,大的关键字基本...

🦄个人主:修修修也

🎏所属专栏:数据

⚙️操作:Visual Studio 2022

​编辑


一.化直接插入排序算法

我们在之前对直接插入排序算法的化部分通过对直接插入排序的分析可以得到一个结论,即:

       直接插入排序的数,如果越接近局部有序,续进行直接插入排序算法时间就会越低.

       所基本有序,就是指小的关字基本在前面,大的关字基本在后面,而不大不小的基本在中.

       例如下面这个数组序列,虽然它还是无序的状态,甚至是局部逆序的状态,但至少它的前8个数据"0-7"都在前半部分,后8个数据"8-15"都在后半部分,这样就比完全逆序状更接近基本有序,相应的算法执行的次数也直接减少了一半:

​编辑

         当我们再进一步,将它们整合的更加接近局部有序一些,可以发现,这时算法的总执行次数又直接减少了一半:​编辑

        而当我们整合到最接近局部有序时,可以发现,这时算法的总执行次数表达式中的n^2项就已经消失了:​编辑


我们已经知道了如果将数整合成局部有序,就可以大大化直接插入排序,问题是如何通过预排序将数列整合成局部有序呢?

其实很简单,我们些数字不断分gap,然后别让相隔gap个元素的一数据保持有序就可以了:

         如下,第一次我们将数组分为8组,然后使相隔8个元素的每组数据都保持有序,即第一组数据"15和7"要调整为顺序,则将其二者调换位置即可,后续七组操作同理:

​编辑

然后我们就可以得到如下数组了:​编辑

         接着,我们再将数组分为4组,让每隔4个元素的数据保持有序,即第一组数据"7,3,15,11"要调整为顺序,则将其看作一个代排数组,然后用直接插入排序将其调整为"3,7,11,15"的顺序,后面7组同理:

​编辑

然后我们就可以得到如下数组:​编辑

         我们继续再将数组分为2组,让每隔2个元素的数据保持有序,即将第一组数据"3,1,7,5,11,9,15,13"直接插入排序,将其调整为"1,3,5,7,9,11,13,15"的顺序,第二组同理:​编辑

 然后我们就可以得到如下数组:​编辑

          然后就是最后一步,我们将数组看作一组,让相邻的两个元素的数据保持有序,即将全组数据直接插入排序,就可以得到最终结果:

​编辑

至此,其实我们直接插入排序的,就是排序算法的思路.


二.希排序介及思路

排序(Shell Sort)是一种插入排序算法.

它的基本思想是:

定一个整数,把待排序文件中所有数据分成gap个,所有距离gap的数据分在同一内,并每一内的数据行排序.

重复上述分和排序的工作,当达到gap=1,所有数据在内排好序.

算法动图演示如下:

​编辑


三.希排序算法的代码实现

算法实现:(以升序)

1. 从下标为0的元素开始,遍到下标为n-gap个元素,我使用end来记录本次理的元素下,用tmp记录gap的元素的数.

2. gap的两个元素行比,如果a[end+gap] < a[end],a[end]的值赋值给a[end+gap],并end减掉gap.

3. 然后无论这次有没有交位置,都将tmp赋值给a[end+gap]的位置,如果没有交,a[end+gap]就是tmp原本的,如果次有交,end减去了gap,会使tmp赋值给原本a[end]的位置.该部分图示如下:​编辑​编辑

4. 当第一完下标为n-gap的元素之后,gap除以2,继续重复1-3步的操作.

5. 不断重复第4步操作,直到最gap1,即行直接插入排序后,本次排序完成.

搞清算法实现步骤后,代码实现就比较简单了,希尔排序代码如下:

//希尔排序(升序

void ShellSort(int* a, int n)

{

    int gap = n;

    //gap>1都是在预排序

    //gap==1时就是直接插入排序了




    while (gap > 1)

    {

        gap /= 2;

        //嫌慢的话可以gap/=3+1.加一是要保证最后一次一定是1




        for (int i = 0; i < n - gap; i++)

        {

            int end = i;

            int tmp = a[i + gap];

            while (end >= 0)

            {

                if (tmp < a[end])

                {

                    a[end + gap] = a[end];

                    end -= gap;

                }

                else

                {

                    break;

                }

            }

            a[end + gap] = tmp;

        }

    }

}

四.希排序算法的时间度分析

希尔排序的时间复杂度的计算是较为的,我们先来看两本官方书籍对该部分的描述:

       希排序的分析是一个复问题,因它的时间是所取“增量”序列的函数,涉及一些数学上尚未解决的难题。因此,到目前止尚未有人求得一种最好的增量序列,但大量的研究已得出一些局部的结论。如有人指出,当增量序列,希排序的时间,其中t排序趟数,

        有人在大量的实验上推出:当n在某个特定范内,希排序所需的比和移次数约为,当,可减少到。增量序列可以有各种取法,但需注意:使增量序列中的没有除1之外的公因子,并且最后一个增量等于1。

                                                                 ——《数据(C言版)》蔚敏

       gap的取法有多种。最初Shell提出取,直到gap=1,后来Knuth提出取有人提出都取奇数好,也有人提出各gap互质为好。无哪一种主都没有得到明。
        排序的时间度的分析很困,在特定情况下可以准确地估算关键码的比次数和象移次数,但想要弄清关键码数和象移次教与增量选择的依关系,并出完整的数学分析,没有人能做到。在Knuth所著的《算机程序设计技巧》第3卷中,利用大量的实验统计资料得出,当n很大,关键码平均比次数和象平均移次数大内,是在利用直接插入排序作子序列排序方法的情况下得到的。                             ——《数据-用面向象方法与C++描述》殷人昆

       因此,当前对于希尔排序的时间复杂度,学术界仍没有一个确切的研究,我们只能在估算希尔排序时间复杂度时借助Knuth大佬的实验统计结果,即采用来近似的估算希排序的时间.


结语

希望排序算法解能大家有所帮助,迎大佬留言或私信与我交流.

有关更多排序相关知可以移步:

【数据 构】八大排序算法 https://blog.csdn.net/weixin_72357342/article/details/135038495?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22135038495%22%2C%22source%22%3A%22weixin_72357342%22%7D&fromshare=blogdetail 学海漫浩浩,我亦苦作舟!关注我,大家一起学,一起!

 相关文章推荐

【数据 构】八大排序之冒泡排序算法

【数据 构】八大排序之希 排序算法

【数据 构】八大排序之直接插入排序算法

【数据 构】八大排序之 简单选择 排序

【数据 构】八大排序之堆排序算法

【数据 构】八大排序之快速排序算法

【数据 构】八大排序算法之 并排序算法

【数据 构】八大排序之 数排序算法


数据构排序算法篇思维导图: 编辑


​编辑

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。