手撕排序算法3:优化版冒泡排序和快速排序的三种方法(包括三数取中,小区间优化,递归版本)(上)

简介: 手撕排序算法3:优化版冒泡排序和快速排序的三种方法(包括三数取中,小区间优化,递归版本)(上)

一.冒泡排序

1.算法思想

冒泡排序,顾名思义,就是在每一趟中将最大的数沉到水底,也就是将最大的数移动到末尾位置,一共进行n-1次

冒泡排序的整体思想是:

1.左右两两比较,大的向后移动,小的向前移动

2.每一趟都会使当前所比较过的元素中最大的那个移动到最后位置

3.一共n-1趟即可,因为对于一个数组来说,如果已经确定好了n-1个数字,又因为一个数组只有n个数字,所以剩下的那一个数字的位置也就唯一确定了

2.代码实现

void BubbleSort(int* a, int n)
{
  int i = 0;
  for (i = 0; i < n - 1; i++)//一共冒泡n-1趟(i控制趟数)
  {
    int flag = 1;//假设有序
    int j = 0;
    for (j = 0; j < n - 1 - i; j++)//(j控制每一趟比较的次数)
      //第一趟比较n-1次,第二趟比较n-2次(因为第二趟就不需要比较最后一个数字了,因为最后一个数字已经是最大的了)....,归纳为n-1-i次
    {
      if (a[j] > a[j + 1])
      {
        Swap(&a[j], &a[j + 1]);
        flag = 0;//发生交换,改为无序
      }
    }
    if (flag == 1)//有序,所以无需再进行排序,直接break
    {
      break;
    }
  }
}

这是冒泡排序的一种优化版本,使用flag标志数组是否已经有序,如果有序,则跳出循环,排序成功.

3.冒泡排序的时间复杂度与稳定性

冒泡排序的时间复杂度是O(N^2),具有稳定性

至于为什么冒泡排序具有稳定性呢?

是因为冒泡排序在每一趟的比较过程中只有当左边元素大于右边元素时才会发生交换,而当左边元素等于右边元素时并不会发生交换,所以冒泡排序具有稳定性

4.冒泡排序,插入排序,选择排序的优劣介绍

插入排序比冒泡排序好,冒泡排序比选择排序好

前面提到过,当数组是有序或者部分有序时,插入排序有奇效(时间复杂度能达到O(N)!!!)

可是我们刚才进行的冒泡排序的优化也可以减少一些不必要的比较啊,那么它们两个到底谁更好呢?

下面给大家举个例子.

总结:优化版本冒泡排序

时间复杂度:O(N^2)

最好排序:O(N)

最差:O(N^2)

1.跟直接插入排序相比来说,直接插入更好

因为:

插入排序的任意性更强,对有序,接近有序,局部有序的适用性更强,所以说直接插入排序是在O(N^2)中的排序算法中非常好的一个算法了

2.很直接选择排序相比来说,冒泡排序更好,因为直接选择排序无论数组是否有序,都进行N^2次,而冒泡排序针对有序或部分有序有一些优化,避免了一些没有任何必要的比较

3.但是数组无序的情况下,冒泡排序还是效率比较差的

二.快速排序

1.算法思想

快速排序是一个非常强大的排序算法,能够很快地解决大多数排序问题,但是要理解起来不是很容易,我们先来看一下快排的单步思想

那么我们该如何实现让6的左边都比6小,6的右边都比6大呢?

下面我们介绍一下"挖坑"法,pivot:英文单词"坑"

我们来看这几张图片

这就是单趟快排的示意图.

2.单趟快排的代码实现

接下来,我们先写一下单趟快排的代码

void QuickSort(int* a, int n)
{
  int begin = 0;
  int end = n - 1;
  int pivot = begin;
  int key = a[begin];
  while (begin < end)
  {
    //左边有坑,右边找小,放到左边
    while (a[end] >= key && begin < end)
    {
      end--;
    }
    if (begin < end)
    {
      //小的放到左边的坑里,自己形成了新的坑位
      a[pivot] = a[end];
      pivot = end;
    }
    //右边有坑,左边找小,放到右边
    while (a[begin] <= key && begin < end)
    {
      begin++;
    }
    if (begin < end)
    {
      //大的放到右边的坑里,自己形成了新的坑位
      a[pivot] = a[begin];
      pivot = begin;
    }
  }
  pivot = begin;
  a[pivot] = key;
}

可见,单趟排序的时间复杂度是O(N),因为begin和end要相遇,且每轮循环只能有一个"指针"在变动,这里所说的"指针"不是C语言所说的指针,而是一种标记而已

3.快排整体思想和代码实现

这时,我们成功让6的左边都小于6,6的右边都大于6,

此时我们想:

如果能让6的左边变为有序,右边也变为有序,那么不就整体有序了吗?

所以在这里我们呢考虑使用分治的思想,也就是递归的方法,也就是缩短区间(大事化小,将一个大问题拆解为若干个子问题,然后逐个击破)

因为当区间缩小到只剩一个值的时候,它一定有序

下面我们来看一张图片

我们发现,只需要对第一次分割出来的左区间和右区间分别进行多次挖坑法,就可以实现整体有序,

其实我们发现,这个快排的递归思想就像是二叉树的深度优先遍历.

下面我们用代码实现一下,如果感觉理解不了下面代码中的这种递归的方式,请仔细看一下上面这张图片,上面把递归调用的整个过程划分的很详细

void QuickSort(int* a, int left,int right)//这里为了进行函数递归,把形参改为左右"指针",方便进行递归
{
  if (left >= right)//当区间长度小于等于1时,无需进行排序了,如果不加这一条,函数将进入死递归
  {
    return;
  }
  int begin = left;
  int end = right;
  int pivot = begin;
  int key = a[begin];
  while (begin < end)
  {
    //左边有坑,右边找小,放到左边
    while (a[end] >= key && begin < end)
    {
      end--;
    }
    if (begin < end)
    {
      //小的放到左边的坑里,自己形成了新的坑位
      a[pivot] = a[end];
      pivot = end;
    }
    //右边有坑,左边找小,放到右边
    while (a[begin] <= key && begin < end)
    {
      begin++;
    }
    if (begin < end)
    {
      //大的放到右边的坑里,自己形成了新的坑位
      a[pivot] = a[begin];
      pivot = begin;
    }
  }
  pivot = begin;
  a[pivot] = key;
  //这里我们将[left,right]这个区间分为这么三个部分
  //[left,pivot-1]  pivot [pivot+1,right]
  QuickSort(a, left, pivot - 1);
  QuickSort(a, pivot + 1, right);
  //快排的递归思想就像是二叉树的深度优先遍历.
  //根 左区间 右区间 根 左区间 右区间 根 左区间 右区间 根 左区间 右区间 .........,
  //单个区间就像是叶子节点
}

上面就是快排的基础代码(还未经过优化的)

相关文章
|
4天前
|
机器学习/深度学习 存储 算法
近端策略优化(PPO)算法的理论基础与PyTorch代码详解
近端策略优化(PPO)是深度强化学习中高效的策略优化方法,广泛应用于大语言模型的RLHF训练。PPO通过引入策略更新约束机制,平衡了更新幅度,提升了训练稳定性。其核心思想是在优势演员-评论家方法的基础上,采用裁剪和非裁剪项组成的替代目标函数,限制策略比率在[1-ϵ, 1+ϵ]区间内,防止过大的策略更新。本文详细探讨了PPO的基本原理、损失函数设计及PyTorch实现流程,提供了完整的代码示例。
100 10
近端策略优化(PPO)算法的理论基础与PyTorch代码详解
|
1月前
|
算法 数据可视化 安全
基于DWA优化算法的机器人路径规划matlab仿真
本项目基于DWA优化算法实现机器人路径规划的MATLAB仿真,适用于动态环境下的自主导航。使用MATLAB2022A版本运行,展示路径规划和预测结果。核心代码通过散点图和轨迹图可视化路径点及预测路径。DWA算法通过定义速度空间、采样候选动作并评估其优劣(目标方向性、障碍物距离、速度一致性),实时调整机器人运动参数,确保安全避障并接近目标。
147 68
|
3天前
|
传感器 算法 物联网
基于粒子群算法的网络最优节点部署优化matlab仿真
本项目基于粒子群优化(PSO)算法,实现WSN网络节点的最优部署,以最大化节点覆盖范围。使用MATLAB2022A进行开发与测试,展示了优化后的节点分布及其覆盖范围。核心代码通过定义目标函数和约束条件,利用PSO算法迭代搜索最佳节点位置,并绘制优化结果图。PSO算法灵感源于鸟群觅食行为,适用于连续和离散空间的优化问题,在通信网络、物联网等领域有广泛应用。该算法通过模拟粒子群体智慧,高效逼近最优解,提升网络性能。
|
2天前
|
机器学习/深度学习 数据采集 算法
基于GWO灰狼优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB2022a,展示了时间序列预测算法的运行效果(无水印)。核心程序包含详细中文注释和操作视频。算法采用CNN-GRU-SAM网络,结合灰狼优化(GWO),通过卷积层提取局部特征、GRU处理长期依赖、自注意力机制捕捉全局特征,最终实现复杂非线性时间序列的高效预测。
|
22小时前
|
算法
基于SOA海鸥优化算法的三维曲面最高点搜索matlab仿真
本程序基于海鸥优化算法(SOA)进行三维曲面最高点搜索的MATLAB仿真,输出收敛曲线和搜索结果。使用MATLAB2022A版本运行,核心代码实现种群初始化、适应度计算、交叉变异等操作。SOA模拟海鸥觅食行为,通过搜索飞行、跟随飞行和掠食飞行三种策略高效探索解空间,找到全局最优解。
|
1天前
|
算法 数据安全/隐私保护 计算机视觉
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
|
1月前
|
算法 数据安全/隐私保护 计算机视觉
基于Retinex算法的图像去雾matlab仿真
本项目展示了基于Retinex算法的图像去雾技术。完整程序运行效果无水印,使用Matlab2022a开发。核心代码包含详细中文注释和操作步骤视频。Retinex理论由Edwin Land提出,旨在分离图像的光照和反射分量,增强图像对比度、颜色和细节,尤其在雾天条件下表现优异,有效解决图像去雾问题。
|
1月前
|
算法 数据安全/隐私保护
室内障碍物射线追踪算法matlab模拟仿真
### 简介 本项目展示了室内障碍物射线追踪算法在无线通信中的应用。通过Matlab 2022a实现,包含完整程序运行效果(无水印),支持增加发射点和室内墙壁设置。核心代码配有详细中文注释及操作视频。该算法基于几何光学原理,模拟信号在复杂室内环境中的传播路径与强度,涵盖场景建模、射线发射、传播及接收点场强计算等步骤,为无线网络规划提供重要依据。
|
1月前
|
机器学习/深度学习 数据采集 算法
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目基于MATLAB2022a实现时间序列预测,采用CNN-GRU-SAM网络结构。卷积层提取局部特征,GRU层处理长期依赖,自注意力机制捕捉全局特征。完整代码含中文注释和操作视频,运行效果无水印展示。算法通过数据归一化、种群初始化、适应度计算、个体更新等步骤优化网络参数,最终输出预测结果。适用于金融市场、气象预报等领域。
基于GA遗传优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
|
21小时前
|
算法 数据可视化 数据安全/隐私保护
一级倒立摆平衡控制系统MATLAB仿真,可显示倒立摆平衡动画,对比极点配置,线性二次型,PID,PI及PD五种算法
本课题基于MATLAB对一级倒立摆控制系统进行升级仿真,增加了PI、PD控制器,并对比了极点配置、线性二次型、PID、PI及PD五种算法的控制效果。通过GUI界面显示倒立摆动画和控制输出曲线,展示了不同控制器在偏转角和小车位移变化上的性能差异。理论部分介绍了倒立摆系统的力学模型,包括小车和杆的动力学方程。核心程序实现了不同控制算法的选择与仿真结果的可视化。
25 14

热门文章

最新文章