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

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

折半插入排序算法解析

一、理解算法思想

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

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

二、算法流程

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

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

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

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

三、代码实现

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 )



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



目录
相关文章
|
5天前
|
算法 开发者 Python
惊呆了!Python算法设计与分析,分治法、贪心、动态规划...这些你都会了吗?不会?那还不快来学!
【7月更文挑战第10天】探索编程巅峰,算法至关重要。Python以其易读性成为学习算法的首选。分治法,如归并排序,将大问题拆解;贪心算法,如找零问题,每步求局部最优;动态规划,如斐波那契数列,利用子问题解。通过示例代码,理解并掌握这些算法,提升编程技能,面对挑战更加从容。动手实践,体验算法的神奇力量吧!
26 8
|
4天前
|
算法 搜索推荐 编译器
算法高手养成记:Python快速排序的深度优化与实战案例分析
【7月更文挑战第11天】快速排序是编程基础,以O(n log n)时间复杂度和原址排序著称。其核心是“分而治之”,通过选择基准元素分割数组并递归排序两部分。优化包括:选择中位数作基准、尾递归优化、小数组用简单排序。以下是一个考虑优化的Python实现片段,展示了随机基准选择。通过实践和优化,能提升算法技能。**
8 3
|
6天前
|
数据采集 搜索推荐 算法
Python基于协同过滤算法进行电子商务网站用户行为分析及服务智能推荐
Python基于协同过滤算法进行电子商务网站用户行为分析及服务智能推荐
|
6天前
|
存储 算法 Python
震撼!Python算法设计与分析,分治法、贪心、动态规划...这些经典算法如何改变你的编程世界!
【7月更文挑战第9天】在Python的算法天地,分治、贪心、动态规划三巨头揭示了解题的智慧。分治如归并排序,将大问题拆解为小部分解决;贪心算法以局部最优求全局,如Prim的最小生成树;动态规划通过存储子问题解避免重复计算,如斐波那契数列。掌握这些,将重塑你的编程思维,点亮技术之路。
14 1
|
6天前
|
机器学习/深度学习 数据采集 算法
Python基于Lasso特征选择、GM算法和SVR回归算法进行财政收入影响因素分析及预测
Python基于Lasso特征选择、GM算法和SVR回归算法进行财政收入影响因素分析及预测
|
6天前
|
数据采集 算法 搜索推荐
Python基于RFM模型和K-Means聚类算法进行航空公司客户价值分析
Python基于RFM模型和K-Means聚类算法进行航空公司客户价值分析
|
6天前
|
数据采集 机器学习/深度学习 算法
Python基于Apriori关联规则算法实现商品零售购物篮分析
Python基于Apriori关联规则算法实现商品零售购物篮分析
|
1天前
|
算法 数据安全/隐私保护
基于GA遗传优化算法的Okumura-Hata信道参数估计算法matlab仿真
在MATLAB 2022a中应用遗传算法进行无线通信优化,无水印仿真展示了算法性能。遗传算法源于Holland的理论,用于全局优化,常见于参数估计,如Okumura-Hata模型的传播损耗参数。该模型适用于150 MHz至1500 MHz的频段。算法流程包括选择、交叉、变异等步骤。MATLAB代码执行迭代,计算目标值,更新种群,并计算均方根误差(RMSE)以评估拟合质量。最终结果比较了优化前后的RMSE并显示了SNR估计值。
15 7
|
4天前
|
算法 数据挖掘
MATLAB数据分析、从算法到实现
MATLAB数据分析、从算法到实现
|
10天前
|
机器学习/深度学习 算法 调度
Matlab|基于改进鲸鱼优化算法的微网系统能量优化管理matlab-源码
基于改进鲸鱼优化算法的微网系统能量管理源码实现,结合LSTM预测可再生能源和负荷,优化微网运行成本与固定成本。方法应用于冷热电联供微网,结果显示经济成本平均降低4.03%,提高经济效益。代码包括数据分段、LSTM网络定义及训练,最终展示了一系列运行结果图表。