7大排序算法-- 直接插入,希尔,冒泡,选择 --精解(上)

简介: 7大排序算法-- 直接插入,希尔,冒泡,选择 --精解

直接插入排序:

插入排序整体来看还是一个挺简单的排序  可以这么比喻 有一群士兵 每个人都有属于自己的编号 但编号是随机的 现在要求他们迅速地按照编号排成一排 那每个士兵都要根据自己的编号去找属于自己的位置  插入排序的思想 跟这个类似

71b0fc818ff3494fbe0a876a19ede131.gif

如上图 我们一开始的数据是有序的 现在插入个数 我们要保证插入数据后我们的这4个数据也是有序的 我们实现的步骤:

① 把插入的数据有一个变量存储(这里我用tmp)

② 从插入数据的前一个数据依次遍历 与tmp比较 如果比tmp大则该数据往后移一位 如果比tmp小 则tmp填入它的前面


如果说给我们一个数组 我们只需把第一个数据看成有序 第二个数据是插入的数据 把他们排成有序 根据这样的思路以此类推 得出这样的代码:

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
      {
                a[end] = tmp;
        break;
      }
    }
  }
}

 我这里是把插入数据的位置作为起始的遍历的位置 把它与前一个数进行比较 当然也可以把插入数据的前一个数据作为比较的起始位置 只不过最后填入数据的时候是 a[end+1]=tmp 具体的边界判断大家下去可以试试


回归我们之前的问题 大家看了上面的代码 觉得这样对嘛? 


其实有一个边界的问题不知道大家是否注意到了没有

就是假设现在有两个数据 第二个数据为插入的数据 此时我们的end指向第二个数据(end=1) 我们与第一个数据比较 假设比较的结果是 第二个数据 要和 第一个数据 交换那么交换后end指向第一个数据 的位置(end=0) 此时我们想把tmp放进去 可是 此时还能进入while的循环嘛?  是不是就不能了 可是我们的tmp还没放进去呢 这样不就出问题了吗?


 也许你会想 “那我们把while(end>0)改成while(end>=0)不就行了嘛” 真的这样就可以纠正问题了嘛?

如果改成那样  现在我们继续刚刚的操作 我们此时 end=0 进去了 比较的时候我们与 end-1 位置的数据比较 0-1=-1 这样是不是越界了呢?所以这样是不可行的

咋们正确的做法应该是在while循环的外面进行tmp的填入:

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;
  }
}

大家这样看 我们此时无论是end=0跳出来 还是比较时跳出来 都会执行tmp的填入 这样不就解决了嘛 大家看是不是这个道理?


直接插入排序的时间复杂度:

现在大家看完插入排序的代码实现 大家算一算这个插入排序的时间复杂度时多少呢?


 首先 我们的最坏的时间复杂度时O(n^2) :这种情况就是我们每次进行插入数据的操作 每次插入数据的前面的每个数据都会往后移动 也就是 9 8 7 6 5 4 3 2 1 排成升序

其次 我们最好的时间复杂度是O(n) 也就是 给我们的数据本身就是有序的 也就只会遍历一遍数据就没了

虽然我们最坏的时间复杂度是O(n^2) 但是这并不代表我们的插入排序就不好了 毕竟一个完全没有顺序的数组还是少见 这样看来内 我们的时间复杂也就没那么大了

我们的直接插入排序整体来讲还是挺好的

稳定性:稳定


冒泡排序:

相信对于这个排序大家应该也不陌生  我们就是 依次遍历 两两比较 每次遍历结束 至少有一个数会被放到它该有的位置

void swap(int* p, int* q)
{
  int tmp = *p;
  *p = *q;
  *q = tmp;
}
void BubbleSort(int* a, int n)//我这里的n是总的数组大小
{
  for (int i = 0; i < n - 1; i++)
  {
    for (int j = 0; j < n - 1 - i; j++)
    {
      if (a[j] > a[j + 1])
      {
        swap(a + j, a + j + 1);
      }
    }
  }
}


冒泡排序的时间复杂度:

这样写出的代码大家来看一下我们的时间复杂度是多少呢?


很显然 我们最坏的时间复杂度:O(n^2)  稳定性:稳定

我们最好的时间复杂度:O(n^2) (因为哪怕我们现在给的数组是有序的 我们还是会全部遍历完才结束)  

那我们是不是可以改进下呢 让它不必每次都要去遍历?

void BubbleSort(int* a, int n)
{
  for (int i = 0; i < n - 1; i++)
  {
        int flag=0;
    for (int j = 0; j < n - 1 - i; j++)
    {
      if (a[j] > a[j + 1])
      {
                flag=1;
        swap(a + j, a + j + 1);
      }
    }
        if(!flag) break;
  }
}

 大家看这样是不是就解决了呢 我们第一遍遍历 如果没有发生交换 那么flag依旧等于0 下一次遍历之前判断 flag是否等于0 如果等于说明 数组已经有序不必再继续遍历了


那现在我们的插入排序 和冒泡排序(改过后)的时间复杂度是差不多的 那到底哪一个会更好一点内? 

75ef313f99ea4170b2aab1e57c031e54.png

大家觉得上面的数组 用插入排序 和 冒泡排序 哪一个会更好呢?

我们比较 他们数之间的比较次数就可以了  大家数一下是多少呢?

插入排序:8次 冒泡排序:7+6次 是不是这样呢

所以我们这样来看的话 还是我们的直接插入排序会更好一点!


总的来讲:如果顺序有序的话 那插入和冒泡是一样的  但如果是局部有序的话或者说是接近有序 那么插入排序的适应性就更好 比较次数也更少  

目录
相关文章
|
23天前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
11 0
|
30天前
|
搜索推荐 算法
排序算法---冒泡&选择&插入总结
排序算法---冒泡&选择&插入总结
14 0
|
3月前
|
搜索推荐 算法
十大排序算法-快排-希尔-堆排-归并-冒泡-桶排-选择-插入-计数-基数
十大排序算法-快排-希尔-堆排-归并-冒泡-桶排-选择-插入-计数-基数
十大排序算法-快排-希尔-堆排-归并-冒泡-桶排-选择-插入-计数-基数
|
3月前
|
数据采集 搜索推荐 算法
【高手进阶】Java排序算法:从零到精通——揭秘冒泡、快速、归并排序的原理与实战应用,让你的代码效率飙升!
【8月更文挑战第21天】Java排序算法是编程基础的重要部分,在算法设计与分析及实际开发中不可或缺。本文介绍内部排序算法,包括简单的冒泡排序及其逐步优化至高效的快速排序和稳定的归并排序,并提供了每种算法的Java实现示例。此外,还探讨了排序算法在电子商务、搜索引擎和数据分析等领域的广泛应用,帮助读者更好地理解和应用这些算法。
37 0
|
5月前
|
搜索推荐 算法
【排序】数据结构——排序算法概念及代码详解(插入、冒泡、快速、希尔)
【排序】数据结构——排序算法概念及代码详解(插入、冒泡、快速、希尔)
|
5月前
|
人工智能 算法 搜索推荐
蓝桥杯宝藏排序题目算法(冒泡、选择、插入)
以下是内容的摘要: 本文介绍了三种排序算法:冒泡排序、选择排序和插入排序。冒泡排序通过不断交换相邻的逆序元素逐步排序,最坏情况下需要 O(n^2) 次比较。选择排序在每轮中找到剩余部分的最小元素并放到已排序序列的末尾,同样具有 O(n^2) 时间复杂度。插入排序则是将每个元素插入到已排序序列的正确位置,时间复杂度也是 O(n^2),但空间复杂度为 O(1)。
|
6月前
|
算法 搜索推荐 Java
Java数据结构 -- 常见算法分析(查找算法、排序算法)精解详解!!!
Java数据结构 -- 常见算法分析(查找算法、排序算法)精解详解!!!
57 0
|
6月前
|
存储 算法 搜索推荐
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
168 1
|
6月前
|
搜索推荐
图解基础排序算法(冒泡、插入、选择)(山东大学实验二)
图解基础排序算法(冒泡、插入、选择)(山东大学实验二)
|
12天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。