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

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

一.直接插入排序简介及思路

直接插入排序(Straight Insertion Sort)是一种简单直观的插入排序算法.

它的基本操作是:

  • 一个数据插入到已经排好的有序表中,从而得到一个新的,数据数增1的有序表.
  • 直到所有的数据插入完为止,得到一个新的有序序列.

在实际生活中,我们玩扑克牌时就使用了插入排序的思想:

算法动图演示如下:


二.直接插入排序的代码实现

算法实现步骤:(以升序为例)

  1. 当表中只有第一个数据的时候它是一定有序的,因此我们第二个元素开始向前面的有序表"插入"数据.
  2. 具体插入方式,使用tmp记录下当前待插入元素,然后tmp从后向前与有序表中的元素逐一比对,如果tmp小于比对元素,则比对元素向后挪动一个位置.
  3. 直到tmp不小于比对元素时,tmp插入到比对元素后面.
  4. 循环将数据向前插入,直到将待排数组的所有数据元素都插入进有序表,排序完成.

清楚了逻辑和概念后,我们的代码实现就比较简单了.代码如下:

//插入排序(升序
void InsertSort(int* a, int n)
{
  for (int i = 1; i < n; i++)
  {
    int end = i - 1;
    int tmp = a[i];
    //将tmp插入到[0,end]这个有序表的区间里
 
    while (end >= 0)
    {
      if (tmp < a[end])  //如果tmp小于比对元素,将比对元素向后挪
      {
        a[end + 1] = a[end];
        end--;
      }
      else       //如果tmp不小于比对元素,将tmp插入到比对元素后面
      {
        break;
      }
    }
    a[end + 1] = tmp;
  }
}

三.直接插入排序的时间复杂度分析

📌最好情况时间复杂度

直接排序的最好情况是每个tmp向前插入时都发现自己恰好不小于前面有序表中的最后一个元素,这时就直接将自己放在自己原本的地方就可以继续向前插入下一个元素了,即数组完全顺序的情况:

易得此时的:

  • 算法执行次数为:
  • 算法时间复杂度为:

📌最坏情况时间复杂度

直接插入的最坏情况是遇到每一个tmp都直到比对到前面有序表的0号位置才插入,即数组完全逆序的情况:

此时算法每趟的交换次数累加起来就是1 + 2 + ...... +(n-2)+(n-1),可以发现当算法执行结束,所有次数累加起来恰好是一个等差数列,我们利用求和公式可得:

  • 算法执行总次数为:
  • 算法时间复杂度为:

四.直接插入排序的优化

我们通过对前面直接插入排序的分析可以发现,当数组整体完全逆序时:

算法的执行总次数为:

算法的执行总次数为:


但是如果我们面对的是前后两部分分别逆序的数组时:

算法的执行总次数为:

算法的执行总次数为:

此时算法的效率就提高了:


如果我们再分为前后四部分逆序的数组时:

算法的执行总次数为:

算法的执行总次数为:

此时算法的效率又提高了:


通过前面的分析,我们可以发现,随着我们分的部分的增加,算法的执行次数在有规律的减少:

分成k部分算法执行总次数有如下关系:

如果我们令k无限大,此时算法的执行次数就可以忽略n^2项,而只剩下1/2n项了

其实k无限大的情况,就是数组被分为只有前后两个元素逆序的情况:

这种情况下,算法的执行总次数:(1+1+......+1+1)

算法的执行总次数:


通过上面的分析,我们可以得到一个结论:

数组元素越接近基本有序,直接插入排序算法的时间复杂度就会越低.

那么我们是不是可以在正式进行插入排序之前数组元素先简单"预排序"一下呢,即在预排序中,我们尽量将大一些的元素放在数组靠后的位置,小一些的元素放在数组靠前的位置,这样再进行直接插入排序就能使效率提高很多.

如果你能够理解这一直接插入排序算法的优化思路,那么恭喜你,你已经理解了希尔排序的思想,接下来我会在另一篇博客中,详细介绍怎样通过这一思路优化直接插入排序算法,最终构造出非常著名的希尔排序算法.

感兴趣的朋友可以直接点击下方文章链接查看希尔排序算法的相关内容:

https://blog.csdn.net/weixin_72357342/article/details/135043566


结语

希望这篇直接插入排序算法详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.

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

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!


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



相关文章
|
3月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
193 6
|
3月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
91 1
|
14天前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
76 29
|
14天前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》图、查找、排序专题考点(含解析)
408考研——《数据结构》图,查找和排序专题考点选择题汇总(含解析)。
66 29
|
14天前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
72 25
|
14天前
|
存储 人工智能 算法
C 408—《数据结构》算法题基础篇—数组(通俗易懂)
408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
58 23
|
1月前
|
存储 人工智能 算法
【C++数据结构——内排序】二路归并排序(头歌实践教学平台习题)【合集】
本关任务是实现二路归并算法,即将两个有序数组合并为一个有序数组。主要内容包括: - **任务描述**:实现二路归并算法。 - **相关知识**: - 二路归并算法的基本概念。 - 算法步骤:通过比较两个有序数组的元素,依次将较小的元素放入新数组中。 - 代码示例(以 C++ 为例)。 - 时间复杂度为 O(m+n),空间复杂度为 O(m+n)。 - **测试说明**:平台会对你编写的代码进行测试,提供输入和输出示例。 - **通关代码**:提供了完整的 C++ 实现代码。 - **测试结果**:展示代码运行后的排序结果。 开始你的任务吧,祝你成功!
36 10
|
1月前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
58 10
|
1月前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
41 7
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
49 2