用调试来帮你分析并拿捏折半插入排序算法的流程

简介: 用调试来帮你分析并拿捏折半插入排序算法的流程

折半插入排序算法解析

一、理解算法思想

每次从原有数据中取出一个数,插入到之前已经排好的序列中,直到所有的数全部取完,该算法过程与直接插入排序算法极为相似,区别就是在插入的时候 高效 的选择位置。

使用二分(折半)查找来选择插入位置

二、算法流程

外层循环用来找到序列中无序的入口

进入无序入口后,记录入口位置元素值并进入二分查找

二分查找结束后,将元素值向依次后覆盖

最后将入口位置的元素值插入到二分查找结束的位置即可

三、代码实现

1、源代码

int main(void)
{
  int arr[6] = { 27,45,50,35,66,32 };
  int len = sizeof(arr) / sizeof(arr[0]);
  cout << "排序前:" << endl;
  for (int i = 0; i < len; i++) {
    cout << arr[i] << " ";
  }
  cout << endl;
  for (int i = 1; i < len ; i++)
  {
    if (arr[i] < arr[i - 1])
    {
      int temp = arr[i]; 
      int low = 0;
      int high = i - 1;  
      while (low <= high) {
        int middle = (low + high) / 2;
        if (temp < arr[middle])
        {
          high = middle - 1;
        }
        else
        {
          low = middle + 1;
        }
      }
      for (int j = i - 1; j >= high + 1; j--)
      {
        arr[j + 1] = arr[j];
      }
      arr[high + 1] = temp;
    }
  }
  cout << "排序后:" << endl;
  for (int i = 0; i < len; i++) {
    cout << arr[i] << " ";
  }
}

解析:


由于不会出现重复元素,所以最后一定会将搜索区间缩小至low与high重合(左右区间端点不断移动)。在最后一次循环时,low、high的值相同,在比较完成后,左右端点发生交错,相差为1,此时要选择一个变量的值作为新插入元素的位置参照。

需要明确的是,在左右端点重合之前,待插入元素必定是能够落在low与high的区间内的,这就决定了tmp一定大于low对应的元素,小于high对应的元素。

而且最终的插入位置应该放在最后比较元素的后一个位置,也就是mid对应位置的后面,所以是mid+1。如果用low表示,就刚好是low,如果用high表示,则是high+ 1。

2、运行效果


ba7933b37d1e43309e4a3328eef042ff.png

四、调试程序,分析算法流程

1、详细的调试过程

1.使用VS编译器,在程序更改序列的的位置设置断点

d14c2f36805445cf8f2e88e09b59080b.png

2.启动调试,可以看到程序已经运行到断点处且无错误

bc57d15c36bf4c6094ddd7a24ad7e5ff.png

3.根据上一个调试结果可以看到第一个程序入口位置是 i = 3,二分查找结束的条件是 low >high,那么继续逐语句调试,观察数组中元素值的变化

e4ff872a578c49dcbcce844a353df894.png


4.上一张图片arr[3]变为了50,随之j--,再次调试的话arr[2]的值也会发生改变

b5038260e6ea44c2adf08c25cd11328f.png

5.可以看到arr[2]的值变为45,那么下一次调试将跳出for循环,arr[1]的将变为入口位置的元素值

0e71d565476a4fc99d91c72b9750ddba.png

6.那么该入口的折半插入排序就完成了,接下来运行到外层for循环,继续寻找无序入口并重复上面的操作

1ef5c5d35c8941e6abb32f5d8c556e5f.png

7.上次调试的情况是当i=5时,进入折半排序入口,流程和前五步一致,所以直接看最终调试结果

ae12f0bbfb4a4dfaae16fe799829ce24.png

d3dc13fc12144b528a7f4b1fd7e0009a.png

2、时间复杂度

对于折半插入排序来说,元素的串位次数没有并发生变化,只是在查找位置是更加快速了,因此该算法与直接插入排序处于同一量级。不过在数据量很大时,要优于直接插入排序,时间复杂度仍为O(n 2 n^2n 2 )



本文到此结束,如有问题务必交流指正,期待你的关注与支持~



目录
相关文章
|
1月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
60 4
|
26天前
|
并行计算 算法 IDE
【灵码助力Cuda算法分析】分析共享内存的矩阵乘法优化
本文介绍了如何利用通义灵码在Visual Studio 2022中对基于CUDA的共享内存矩阵乘法优化代码进行深入分析。文章从整体程序结构入手,逐步深入到线程调度、矩阵分块、循环展开等关键细节,最后通过带入具体值的方式进一步解析复杂循环逻辑,展示了通义灵码在辅助理解和优化CUDA编程中的强大功能。
|
1月前
|
算法
PID算法原理分析
【10月更文挑战第12天】PID控制方法从提出至今已有百余年历史,其由于结构简单、易于实现、鲁棒性好、可靠性高等特点,在机电、冶金、机械、化工等行业中应用广泛。
|
2月前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
59 4
|
1月前
|
算法
PID算法原理分析及优化
【10月更文挑战第6天】PID控制方法从提出至今已有百余年历史,其由于结构简单、易于实现、鲁棒性好、可靠性高等特点,在机电、冶金、机械、化工等行业中应用广泛。
|
2月前
|
算法 程序员 Python
程序员必看!Python复杂度分析全攻略,让你的算法设计既快又省内存!
在编程领域,Python以简洁的语法和强大的库支持成为众多程序员的首选语言。然而,性能优化仍是挑战。本文将带你深入了解Python算法的复杂度分析,从时间与空间复杂度入手,分享四大最佳实践:选择合适算法、优化实现、利用Python特性减少空间消耗及定期评估调整,助你写出高效且节省内存的代码,轻松应对各种编程挑战。
41 1
|
1月前
|
算法 Java 索引
数据结构与算法学习十五:常用查找算法介绍,线性排序、二分查找(折半查找)算法、差值查找算法、斐波那契(黄金分割法)查找算法
四种常用的查找算法:顺序查找、二分查找(折半查找)、插值查找和斐波那契查找,并提供了Java语言的实现代码和测试结果。
21 0
|
1月前
|
算法 安全 Go
Python与Go语言中的哈希算法实现及对比分析
Python与Go语言中的哈希算法实现及对比分析
40 0
|
29天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
6天前
|
算法 数据安全/隐私保护 索引
OFDM系统PAPR算法的MATLAB仿真,对比SLM,PTS以及CAF,对比不同傅里叶变换长度
本项目展示了在MATLAB 2022a环境下,通过选择映射(SLM)与相位截断星座图(PTS)技术有效降低OFDM系统中PAPR的算法实现。包括无水印的算法运行效果预览、核心程序及详尽的中文注释,附带操作步骤视频,适合研究与教学使用。
下一篇
无影云桌面