拒绝水文!八大排序(一)【适合初学者】直接插入排序和希尔排序

简介: 拒绝水文!八大排序(一)【适合初学者】直接插入排序和希尔排序


大家好,我是纪宁。

这篇文章将向大家介绍直接插入排序算法和希尔排序算法。

直接插入排序

直接插入排序是一个简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

像你玩扑克牌一样,每接到一张排,会习惯性的将它插入到合适的位置当中,最后你会得到一副整齐的牌,插入排序就是这样的原理。

插入排序动态图解

假如现在要进升序排序,那么就需要从第二个数据开始依次 ‘插入’ 到原序列。

具体步骤(以升序为例子)

从第二个数据开始,先保存这个数据 A,然后将数据 A 依次与它前面的数据进行比较,如果数据A 小于前面的数(说明A的位置应该在这个数前面),那么前面的数就后移一个位置,直到数据A 大于等于前面的某个数,就将数据A 放在这个数的后面(这个数后面位置的数已经后移到自身下一个位置了)

代码实现

void InsertSort(int* a, int n)//直接插入排序
{
  for (int i = 1; i < n; i++)
  {
    int end = i;//从第二个位置开始
    int tmp = a[end];//先保存这个值
    while (end > 0)
    {
      if (tmp < a[end - 1])
      {
        a[end] = a[end - 1];
        end--;
      }
      else
      {
        break;//如果不符合,就直接退出了
      }
    }
    a[end] = tmp;
  }
}

易错点:要使用 tmp 与前面的各个值进行依次比较(不能使用 a[end] ),因为 end 的值一直在变。每次插入都只能将一个数插入到原来的序列中,而插入的数就是这个 tmp。

复杂度分析

在最坏情况下,每趟都要比较 ‘满’,那么从第二个开始,就要依次比较 1 2 3 4 … n ,累加得:量级为 N^2。但在最好情况下(有序),这个人排序只需要遍历一次就可以完成排序了,量级为 N,所以在这个序列接近有序的时候,直接插入排序的效率可以接近O(N)

插入排序没有开额外的空间。并且从后往前按顺序排,遇到等于的就停下,所以这个排序很稳定。

时间复杂度:O(N^2)

空间复杂度:O(1)

稳定性:不稳定

希尔排序

插入排序是一个非常好的排序,特别是在序列接近有序的情况下,效率甚至可以达到接近 O(N),那么如何能设计一个算法先对数据先进行预排序,使序列在整体进行插入排序之前能够达到一个接近有序的状态呢?

希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

具体步骤就是将这个数据分为多组,每组成员之间间隔 gap个数据,每组进行插入排序,这样可以使小的数尽量在前面,大的数尽量在后面;然后使 gap按规模递减,重复上面的步骤,最后当gap等于1的时候,就是直接插入排序,并且此时的序列已经是非常接近有序的状态了。

代码实现

第一种,分组,对每一组进行分别排序。

void ShellSort(int* a, int n)//希尔排序
{
  int gap = n / 3;
  while (gap >= 1)
  {
    for (int z = 0; z < gap; z++)//gap组数据
    {
      for (int i = z; i < n - gap; i += gap)//对一组进行直接插入排序
      {
        int end = i;
        int tmp = a[end + gap];
        for (int j = end; j < n-gap; j += gap)
        {
          while (end>=0)
          {
            if (tmp < a[end])
            {
              a[end + gap] = a[end];
            }
            else
            {
              break;
            }
            end -= gap;
          }
          a[end + gap] = tmp;
        }
      }
    }
    gap /= 2;//调整gap的值
  }
}

特点:思路较为简单,但循环较多,代码较复杂。

第二种,分组,但整体顺序是从头开始依次往下,插入排序的时候每次跳过 gap 个数据。

void ShellSort(int* a, int n)//希尔排序
{
  int gap = n / 3;
  while (gap >= 1)
  {
    for (int i = 0; i < n - gap; i++)
    {
      int end = i;
      int tmp = a[end + gap];
      for (int j = end; j < n-gap; j += gap)
      {
        while (end>=0)
        {
          if (tmp < a[end])
          {
            a[end + gap] = a[end];
          }
          else
          {
            break;
          }
          end -= gap;
        }
        a[end + gap] = tmp;
      }
    }
    gap /= 2;  
  }
}

初学者不好思考,但是理解之后代码更简单好控制,不易出错。

复杂度分析

时间复杂度:O(N^1.3) 接近于O(N*logN)

空间复杂度:O(1)

稳定性:不稳定

相关文章
|
编译器 C语言 开发者
技术经验解读:什么是耦合和解耦
技术经验解读:什么是耦合和解耦
4030 1
|
存储 搜索推荐 算法
【数据结构】排序(插入、选择、交换、归并) -- 详解(上)
【数据结构】排序(插入、选择、交换、归并) -- 详解(上)
18569 0
|
人工智能 搜索推荐 算法
【数据结构】排序(插入、选择、交换、归并) -- 详解(下)
【数据结构】排序(插入、选择、交换、归并) -- 详解(下)
|
人工智能 搜索推荐
【数据结构】插入排序详细图解(一看就懂)
【数据结构】插入排序详细图解(一看就懂)
1041 0
|
算法 异构计算 并行计算
|
4天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1682 6
|
9天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1622 1
|
6天前
|
SQL 人工智能 前端开发
QoderWake 1.0 正式发布:从桌面里的 Agent,到工作现场的数字员工
QoderWake v1.0正式发布:企业级数字员工团队平台。支持“一句话建岗”,预置10类特训岗位;Waker常驻钉钉/飞书群,@即响应、自动协作、跨任务记忆;具备定时/事件/API多触发方式与统一任务看板;已沉淀27.6万条记忆、12.3万项技能,助力组织实现人机协同增效。
724 1
|
10天前
|
网络协议 Linux iOS开发
【2026实测】Wireshark下载+安装+汉化+使用教程(图文版,巨详细)
Wireshark 是一款免费开源的网络协议分析工具,可实时捕获、解析并可视化数据包,助你诊断网络故障、分析通信协议(如HTTP、DNS、TCP等)。支持Windows/macOS/Linux,含中文界面,新手入门便捷。(239字)

热门文章

最新文章