十大经典排序算法详解(二)希尔排序,归并排序,快速排序(上)

简介: 十大经典排序算法详解(二)希尔排序,归并排序,快速排序

十大经典排序算法-希尔排序,归并排序,快速排序


前言


这是十大经典排序算法详解的第二篇,这是之前第一篇文章的链接:十大经典排序算法详解(一)冒泡排序,选择排序,插入排序,没有看过的小伙伴可以看一下.


每次讲解都是先采用文字的方式帮助大家先熟悉一下算法的基本思想,之后我会在通过图片的方式来帮助大家分析排序算法的动态执行过程,这样就能够帮助大家更好的理解算法.


每次的图画起来都比较的繁琐,真的很耗费时间.所以如果你觉得文章写得还可以或者说对你有帮助的话,你可以选择一键三连,或者选择关注我的公众号:萌萌哒的瓤瓤 ,这对我真的很重要.UP在此谢谢各位了.


废话不多说了,下面开始我们的正文部分吧!!!


1-希尔排序


算法思想:


其实希尔排序的思想很简单,因为希尔排序的基本思想就是第一篇中间讲解的关于插入排序的基本思想,只是希尔排序相比较与插入排序多加了一步就是确定步长.之前在插入排序的过程中,我们的步长是固定的即为1,在希尔排序中我们的步长是不固定的,一开始数组长度的一半,之后每次分组排序之后步长就再减半,直到步长到1为止.这时候我们的排序就已经完成了.


说完了,那我们接下来还是通过图解的方式来帮助大家更好的理解希尔排序吧:


20210125134856676.png


看完上面的图之后相信大家就基本了解希尔排序算法的思想了,那么接下来我们还是来分析一下希尔排序算法的特点吧:


希尔排序算法是不稳定的,这里大家可能会产生这样的疑问,本身希尔排序算法的本质就是插入排序,只不过是多了一步确定步长的过程,为什么插入排序就是稳定的,但是希尔排序缺失不稳定的呢?其实重点就是在分组之后,大家都知道在一个分组里面进行一次插入排序肯定是稳定的,关键就在于希尔排序的过程中会出现多次分组,那么就会出现在之前的分组里面是稳定的,但是到下一次分组的时候就会出现不稳定的情况.


说这么多还不如直接来个例子给大家看一下,大家就知道了:


20210125144332886.png


希尔排序是 第一个 在时间复杂度上突破O(N*N)的算法,这一点是非常有意义的.时间复杂度仅为O(N*log N)


算法图解:


20210125133813402.gif


示例代码:


按照算法思想不改动的版本:


public static void main(String[] args) {
    int []num ={7,4,9,3,2,1,8,6,5,10};
    long startTime=System.currentTimeMillis(); 
    //规定步长
    for(int step=num.length/2;step>0;step/=2) {
      System.out.println("步长为"+step+"的分组排序:");
      //步长确定之后就需要分批次的对分组进行插入排序
      for(int l=0;l<step;l++) {
        //插入排序的代码
        for(int i=l+step;i<num.length;i+=step) {
          int temp=num[i];
          int j=i;
          while(j>0&&temp<num[j-step]) {
            num[j]=num[j-step];
            j-=step;
            //这里需要注意一点就是j-step可能会越界,所以我们需要继续进行判断
            //之前在插入排序中,步长始终是1,所以在while循环那里就会阻断,但是现在步长会发生变化
            //所以我们需要在这里提前进行判断,否则金辉发生数组越界的情况
            if(j-step<0)
              break;
          }
          if(j!=i) {
            num[j]=temp;
          }
        }
        System.out.println("   "+l+"号分组排序:");
        for(int k=0;k<num.length;k++)
          System.out.print(num[k]+" ");
        System.out.println();
      }
      System.out.println();
    }
    long endTime=System.currentTimeMillis(); 
    System.out.println("程序运行时间: "+(endTime-startTime)+"ms"); 
  }

20210125114843506.png

但是大家会发现如果真的按照希尔排序的思想这样做得的话,我们会发现用了三层for循环,那么很显然时间复杂度就会达到我们目前遇到的最坏的情况即O(N*N*N),所以我们需要进行改进,主要就是改进分组排序的过程,之前我们是确定完步长之后,就通过for循环进行循环分组的排序,这里我们修改成直接和下一个for循环一起,直接进行循环分组


改进后的代码:


public static void main(String[] args) {
    int []num ={7,4,9,3,2,1,8,6,5,10};
    long startTime=System.currentTimeMillis();  
    for(int step=num.length/2;step>0;step/=2) {
      System.out.println("步长为"+step+"的分组排序:");
      System.out.println("循环分组排序:");
      for(int j=step;j<num.length;j++) {
        int temp=num[j];
        int k=j;
        while(k-step>=0&&temp<num[k-step]) {
          num[k]=num[k-step];
          k-=step;
        }
        num[k]=temp;
        for(int l=0;l<num.length;l++)
          System.out.print(num[l]+" ");
        System.out.println();
      }
    }
    long endTime=System.currentTimeMillis(); 
    System.out.println("程序运行时间: "+(endTime-startTime)+"ms"); 
  }

20210125150908819.png

改进之后的算法之使用了两层for循环,真的让时间复杂度达到了O(N*log N)


复杂度分析:

理解完希尔排序的基本思想之后,我们就需要来分析一下他的时间复杂度,空间复杂度.


时间复杂度


希尔排序的时间复杂度在各情况下,主要就取决于元素的个数以及分组的次数,我们分析得到分组的次数刚好就是log N,所以我们可以得到希尔排序的时间复杂度仅为O(N*log N)


空间复杂度


这个我们可以看到我们整个排序的过程中只增加一个存储Key的位置,所以希尔排序的空间复杂是常量级别的仅为O(1).


相关文章
|
3月前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
81 4
|
3月前
|
存储 搜索推荐 Python
用 Python 实现快速排序算法。
快速排序的平均时间复杂度为$O(nlogn)$,空间复杂度为$O(logn)$。它在大多数情况下表现良好,但在某些特殊情况下可能会退化为最坏情况,时间复杂度为$O(n^2)$。你可以根据实际需求对代码进行调整和修改,或者尝试使用其他优化策略来提高快速排序的性能
152 61
|
4月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
82 1
|
4月前
|
存储 搜索推荐 算法
【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析
【排序算法(二)】——冒泡排序、快速排序和归并排序—>深层解析
|
2天前
|
算法 数据安全/隐私保护 计算机视觉
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
|
1月前
|
算法 数据安全/隐私保护 计算机视觉
基于Retinex算法的图像去雾matlab仿真
本项目展示了基于Retinex算法的图像去雾技术。完整程序运行效果无水印,使用Matlab2022a开发。核心代码包含详细中文注释和操作步骤视频。Retinex理论由Edwin Land提出,旨在分离图像的光照和反射分量,增强图像对比度、颜色和细节,尤其在雾天条件下表现优异,有效解决图像去雾问题。
|
1月前
|
算法 数据可视化 安全
基于DWA优化算法的机器人路径规划matlab仿真
本项目基于DWA优化算法实现机器人路径规划的MATLAB仿真,适用于动态环境下的自主导航。使用MATLAB2022A版本运行,展示路径规划和预测结果。核心代码通过散点图和轨迹图可视化路径点及预测路径。DWA算法通过定义速度空间、采样候选动作并评估其优劣(目标方向性、障碍物距离、速度一致性),实时调整机器人运动参数,确保安全避障并接近目标。
147 68
|
1月前
|
算法 数据安全/隐私保护
室内障碍物射线追踪算法matlab模拟仿真
### 简介 本项目展示了室内障碍物射线追踪算法在无线通信中的应用。通过Matlab 2022a实现,包含完整程序运行效果(无水印),支持增加发射点和室内墙壁设置。核心代码配有详细中文注释及操作视频。该算法基于几何光学原理,模拟信号在复杂室内环境中的传播路径与强度,涵盖场景建模、射线发射、传播及接收点场强计算等步骤,为无线网络规划提供重要依据。
|
1天前
|
算法
基于SOA海鸥优化算法的三维曲面最高点搜索matlab仿真
本程序基于海鸥优化算法(SOA)进行三维曲面最高点搜索的MATLAB仿真,输出收敛曲线和搜索结果。使用MATLAB2022A版本运行,核心代码实现种群初始化、适应度计算、交叉变异等操作。SOA模拟海鸥觅食行为,通过搜索飞行、跟随飞行和掠食飞行三种策略高效探索解空间,找到全局最优解。
|
1天前
|
算法 数据可视化 数据安全/隐私保护
一级倒立摆平衡控制系统MATLAB仿真,可显示倒立摆平衡动画,对比极点配置,线性二次型,PID,PI及PD五种算法
本课题基于MATLAB对一级倒立摆控制系统进行升级仿真,增加了PI、PD控制器,并对比了极点配置、线性二次型、PID、PI及PD五种算法的控制效果。通过GUI界面显示倒立摆动画和控制输出曲线,展示了不同控制器在偏转角和小车位移变化上的性能差异。理论部分介绍了倒立摆系统的力学模型,包括小车和杆的动力学方程。核心程序实现了不同控制算法的选择与仿真结果的可视化。
28 15