首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【数据结构】排序算法---希尔排序(动图演示)

【数据结构】排序算法---希尔排序(动图演示)

作者头像
Crossoads
发布2024-10-22 08:22:14
发布2024-10-22 08:22:14
1.7K00
代码可运行
举报
文章被收录于专栏:汇编语言汇编语言
运行总次数:0
代码可运行

1. 定义

希尔排序(英语:Shell sort),也称为缩小增量排序法,是[直接插入排序]的一种改进版本。希尔排序以它的发明者希尔(英语:Donald Shell)命名。是第一个突破

O(n^2)

的排序算法,它与插入排序的不同之处在于,它会优先比较距离较远的元素。

2. 算法步骤

排序对不相邻的记录进行比较和移动:

  1. 将待排序序列分为若干子序列(每个子序列的元素在原始数组中间距相同);
  2. 对这些子序列进行插入排序;
  3. 减小每个子序列中元素之间的间距,重复上述过程直至间距减少为1。

3. 动图演示

基本思想:先选定一个整数(通常是

gap = n/3+1

),把待排序文件所有记录分成各组,所有的距离相等的记录分在同一组内,并对每一组内的记录进行排序,然后

gap=gap/3+1

得到下一个整数,再将数组分成各组,进行插入排序,当

gap=1

时,就相当于直接插入排序。

它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接入排序算法的。

gap > 1

时都是预排序,目的是让数组更接近于有序。当

gap == 1

时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。

4. 性质

稳定性

希尔排序是一种不稳定的排序算法。

空间复杂度

希尔排序的空间复杂度为

O(1)

时间复杂度

希尔排序的最优时间复杂度为

O(n)

希尔排序的平均时间复杂度和最坏时间复杂度与间距序列的选取有关。设间距序列为

H

,有

H

的两种经典选取方式,这两种选取方式均使得排序算法的复杂度降为级别

O(n^2)

希尔排序的平均时间复杂度可以降为

O(n^{1.3})

下面是希尔排序时间复杂度的估算: 外层循环: 外层循环的时间复杂度可以直接给出为:

O(log_2n)

或者

O(log_3 n)

,即

O(logn)

内层循环:

在这里插入图片描述
在这里插入图片描述

假设一共有n个数据,合计gap组,则每组为n/gap个;在每组中,插入移动的次数最坏的情况下为

1 + 2 + 3 + .... + ({n\over gap} - 1)

,一共是gap组,因此: 总计最坏情况下移动总数为:

gap∗[1 + 2 + 3 + .... + ({n \over gap} - 1)]

gap取值有(以除3为例):n/3 n/9 n/27 … 2 1

  • 当gap为n/3时,移动总数为:
{n \over 3}*(1+2)=n
  • 当gap为n/9时,移动总数为:
{n \over 9}*(1+2+3+....+8)={n \over 9}*{8(1+8) \over 2}=4n
  • 最后一躺,gap=1即直接插入排序,内层循环排序消耗为n

通过以上的分析,可以画出这样的图:

因此,希尔排序在最初和最后的排序的次数都为n,即前一阶段排序次数是逐渐上升的状态,当到达某一顶点时,排序次数逐渐下降至n,而该顶点的计算暂时无法给出具体的计算过程

希尔排序时间复杂度不好计算,因为gap的取值很多,导致很难去计算,因此很多书中给出的希尔排序的时间复杂度都不固定。《数据结构(C语言版)》— 严蔚敏书中给出的时间复杂度为:

5. 算法分析

希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第4版)》的合著者Robert Sedgewick提出的。

6. 代码实现

C语言

代码语言:javascript
代码运行次数:0
运行
复制
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		//推荐写法:除3
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

Python

代码语言:javascript
代码运行次数:0
运行
复制
def shellSort(arr):
    import math
    gap=1
    while(gap < len(arr)/3):
        gap = gap*3+1
    while gap > 0:
        for i in range(gap,len(arr)):
            temp = arr[i]
            j = i-gap
            while j >=0 and arr[j] > temp:
                arr[j+gap]=arr[j]
                j-=gap
            arr[j+gap] = temp
        gap = math.floor(gap/3)
    return arr

Java

代码语言:javascript
代码运行次数:0
运行
复制
public static void shellSort(int[] arr) {
    int length = arr.length;
    int temp;
    for (int step = length / 2; step >= 1; step /= 2) {
        for (int i = step; i < length; i++) {
            temp = arr[i];
            int j = i - step;
            while (j >= 0 && arr[j] > temp) {
                arr[j + step] = arr[j];
                j -= step;
            }
            arr[j + step] = temp;
        }
    }
}

C++

代码语言:javascript
代码运行次数:0
运行
复制
template<typename T>
void shell_sort(T array[], int length) {
    int h = 1;
    while (h < length / 3) {
        h = 3 * h + 1;
    }
    while (h >= 1) {
        for (int i = h; i < length; i++) {
            for (int j = i; j >= h && array[j] < array[j - h]; j -= h) {
                std::swap(array[j], array[j - h]);
            }
        }
        h = h / 3;
    }
}

Go

代码语言:javascript
代码运行次数:0
运行
复制
func shellSort(arr []int) []int {
        length := len(arr)
        gap := 1
        for gap < length/3 {
                gap = gap*3 + 1
        }
        for gap > 0 {
                for i := gap; i < length; i++ {
                        temp := arr[i]
                        j := i - gap
                        for j >= 0 && arr[j] > temp {
                                arr[j+gap] = arr[j]
                                j -= gap
                        }
                        arr[j+gap] = temp
                }
                gap = gap / 3
        }
        return arr
}

结语

今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。

也可以点点关注,避免以后找不到我哦!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 定义
  • 2. 算法步骤
  • 3. 动图演示
  • 4. 性质
  • 5. 算法分析
  • 6. 代码实现
    • C语言
    • Python
    • Java
    • C++
    • Go
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档