首页 > 其他分享 >希尔排序

希尔排序

时间:2025-01-12 11:55:28浏览次数:1  
标签:arr 插入排序 gap 希尔 增量 排序 复杂度

希尔排序(Shell Sort),也称为递减增量排序算法,是插入排序的一种改进版本。它通过将原始数据集合分割成若干个较小的子集合,对每个子集合进行插入排序,以此来改善插入排序在处理大规模数据时效率较低的问题。

1. 基本原理

希尔排序的核心在于它引入了一个增量序列。排序开始时,增量较大,数据集合被分成若干个跨度较大的子序列,对这些子序列分别进行插入排序,使得数据元素大致有序。随着排序的进行,增量逐渐减小,子序列的跨度变小,最后当增量为1时,整个数据集合就如同进行一次普通的插入排序,但此时数据已经接近有序,插入排序能更高效地完成排序工作。

2. 算法步骤

  1. 选择增量序列:常见的增量序列有多种,例如 Hibbard 增量序列(\(2^k - 1\))等。这里以简单的 n / 2 序列为例(n 为数组长度),每次将增量除以2,直到增量为1。
  2. 分组插入排序
    • 对于每个增量 gap,将数组分成 gap 组,每组内的元素间隔为 gap。例如,当 gap = 3 时,数组 [1, 2, 3, 4, 5, 6] 会被分为 [1, 4][2, 5][3, 6] 三组。
    • 对每组数据进行插入排序。在插入排序过程中,将每组内的元素与同组内前面的元素进行比较,如果需要则交换位置,使得每组内的元素有序。
  3. 减小增量并重复:逐步减小增量 gap,重复上述分组插入排序的过程,直到 gap 变为1。当 gap 为1时,整个数组就只剩下一组,此时进行的插入排序将完成最终的排序工作。

3. 代码实现

以下是Python语言实现希尔排序的代码:

def shell_sort(arr):
    n = len(arr)
    gap = n // 2
    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        gap //= 2
    return arr

4. 算法分析

  • 时间复杂度:希尔排序的时间复杂度分析较为复杂,它取决于增量序列的选择。以常见的 n / 2 增量序列为例,其时间复杂度约为 \(O(n^{1.5})\) 。在最好情况下,当数据已经基本有序时,时间复杂度接近 \(O(n)\) 。而最坏情况下,时间复杂度为 \(O(n^2)\) 。
  • 空间复杂度:希尔排序在排序过程中只需要几个临时变量,所以空间复杂度为 \(O(1)\) 。
  • 稳定性:希尔排序是不稳定的排序算法。例如,在排序过程中,相同元素可能会因为增量分组的原因,在不同组内移动,导致其相对顺序发生改变。

标签:arr,插入排序,gap,希尔,增量,排序,复杂度
From: https://www.cnblogs.com/codersgl-blog/p/18666813

相关文章

  • 归并排序
    归并排序(MergeSort)是一种基于分治思想的高效排序算法。它将一个大的数组逐步分解为多个小数组,然后将这些小数组排序后再合并起来,最终得到一个有序的大数组。以下为你详细介绍:1.基本原理分解:将待排序的数组不断地分成两个大致相等的子数组,直到每个子数组只包含一个元素(单个元......
  • 快速排序
    快速排序(QuickSort)是一种高效的排序算法,采用了分治(DivideandConquer)的策略。以下为你详细介绍:1.基本原理从待排序的数据集中选择一个元素作为基准值(pivot)。基准值的选择方法多样,常见的有选择第一个元素、最后一个元素或者中间元素等。重新排列数据集,将所有小于基准值的元......
  • 选择排序
    选择排序(SelectionSort)是一种简单直观的排序算法。它的工作原理是每一趟从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。以下是选择排序的详细介绍:1.算法步骤初始状态:假设有一个长度为n的数组arr,待排序的元素集合为整......
  • 插入排序
    插入排序(InsertionSort)是一种简单直观的排序算法,它的工作原理类似于扑克牌的整理过程。在摸牌时,玩家会将每张新摸到的牌插入到手中已有的有序牌中的合适位置。1.算法步骤初始状态:将数组分为已排序和未排序两部分。初始时,数组的第一个元素被认为是已排序部分,其余元素是未排序......
  • 拓补排序板子(邻接表实现)
    #include<iostream>#include<vector>usingnamespacestd;constintmaxn=2e5+5;vector<int>graph[maxn];//邻接表voidaddedge(intu,intv){graph[u].emplace_back(v);}intindegree[maxn];//入度表intmain(){intn,m;cin>>n>......
  • 课程表(拓补排序)
    题目链接:https://leetcode.cn/problems/course-schedule-ii/description/题意:给定n门课程,规定只有学完某一个课程才能继续学下一门课程,让你输出学习顺序。如果成环,则返回空数组思路:拓补排序,入度删除法需要提前准备一个indegree数组用来统计每个节点的入度大小,用数组模拟双端......
  • 20250108@Excel(排序问题+文本格式转换+查找多条件的个数)
    1.需求:首行标题需要显示 百分比问题:直接="时间进度:"&E1/E2,显示常规解决方法:使用text函数转换格式2.需求:当需要对某些数值排序时,如果出现相同数值,需要做并列排名问题:使用rank排序会出现中断层排名,如图,2之后是4解决方法:数与数之间进行比较,计算布尔值false的个数。3......
  • php二维数组根据某个字段排序
    1$worderData=[2[3'id'=>1,4'name'=>'张三',5'distance'=>0.1,6......
  • 2.6.桶排序
    桶排序桶排序也是一种非常快的排序算法,但是对于个别数组中某个元素比较大的情况比较费内存。它的实现分为三个步骤:第一步,根据数组创建桶。具体桶的个数取决于数组中元素的大小,所谓桶其实也是一个数组,只不过桶的索引代表数组的元素,而索引值代表在原数组中此元素的个数,例如......
  • 二分+排序
    https://codeforces.com/contest/2053/problem/Dhttps://blog.csdn.net/weixin_61825750/article/details/144799098#include<bits/stdc++.h>#definelcp<<1#definercp<<1|1#defineINF2e9usingnamespacestd;#defineendl'\n'us......