排序算法——快速排序

ops/2024/11/19 11:50:05/

目录

一、快速排序的原理

二、快速排序的过程

三、代码的实现

四、代码的优化

总结


一、快速排序的原理

快速排序的思想是分治法,将一个大问题分割成几个小问题解决,首先选择一个数作为分水岭,然后让比该数大的都在它的右边,比它小的都在它左边,将一个大问题分割成了两个问题,用同样的方法对两边分别操作,最后呈现出来的就是排好序的整体。(以升序为例)

二、快速排序的过程(以升序为例)

我定义一个数组a[6]来演示,让low指向低下标,high指向高下标

一般让第一个数作为分水岭split=a[0],然后将split和a[5]进行比较,a[5]>split,不用操作,接着high减一,

然后比较split和a[4],split<a[4],任然不用操作,high再减一,

然后将split和a[3]进行比较,split>a[3],将a[3]放到a[0]的位置,然后high减一,由于此时的low任然是0,但是a[0]是刚刚赋的值,已经比较过了,下一次无需再比较,所以移动之后low加一,

然后比较split和a[1],split<a[1],将a[1]的值放到a[3]中去,并且low加一,由于a[3]是刚刚赋的值,已经比较过了,下次无需再比较,所以还要high减一,

然后比较split和a[2],split>a[2],将a[2]放到a[1]中,并且low加一,high减一, 

当low不小于high的时候,将split放回数组中,放到a[low]的位置,(数组中元素的个数为奇数时,low=high结束,为偶数时,low大于high结束,总之只有low<high才进行比较)

此时第一次分割已经完成,split左边的值都比它小,右边的值都比它大,但是很明显,整个数组并没有排序好,但是后面只需对左边和右边进行相同的操作即可,问题的本质没有改变,经过多次分割整个数组就被排好序了。 (使用递归实现)

左右分别操作的时候,左边的high变成了split的下标减一,右边的low变成了split的下标加一,把左右当成新数组处理即可。

注意:如果split的初始值是a[0],就要从high开始比较,如果是最后一位数,就要从low开始比较,并且比较一定是左右交替的!!!

三、代码的实现

//分割操作
int findsplit(int ints[], int low, int high)
{int split = ints[low];while (low < high){while (low < high){if (ints[high] < split){ints[low] = ints[high];low++;//由于会产生一次多余的比较,所以low++规避,减少比较次数break;}high--;}while (low < high){if (ints[low] > split){ints[high] = ints[low];high--;//同上break;}low++;}}ints[low] = split;return low;
}//递归排序
void rapidselect(int ints[], int low, int high)
{//递归函数退出的条件if (low >= high){return;}int splitindex;splitindex = findsplit(ints, low, high);//split左侧排序rapidselect(ints, low, splitindex - 1);//split右侧排序rapidselect(ints, splitindex + 1, high);
}

四、代码的优化

上面的代码存在一点缺陷,如果a[0]是数组中的极值,那么整个过程并没有达到我们想要的效果,因为所有的数据任然在一边,运行速度受到影响。那么可以写一个函数求一下数组的大致中位数,尽量将数组平均分成两部分。代码如下:

int getmid(int a[], int low, int high)
{int mid = (low + high) / 2;//比较三者的关系if (a[low] < a[mid]){if (a[high] > a[mid])return mid;else if (a[low] < a[high])return high;elsereturn low;}else{if (a[mid] > a[high])return mid;else if (a[high] > a[low])return low;elsereturn high;}
}

将split初始化为这个大致的中位数即可做到尽量将数组均分。 

总结

根据计算,快速排序的排序次数log2(n),n为数组的元素个数,比如一个拥有16个元素的数组,使用冒泡排序需要排序15次(n-1次),而快速排序只需要四次(以2为底,16的对数),速度大大提高,弥补了冒泡排序循环次数多的缺点。

本节就到这里了,不懂的可以私信我,代码有不对的地方,也欢迎大家为我斧正。祝大家天天进步!


http://www.ppmy.cn/ops/134958.html

相关文章

【数据结构初阶】栈和队列的建立

栈 概念和结构 栈是一种特殊的线性表&#xff0c;它只允许一端进行插入和删除数据操作&#xff0c;这一端被称为栈顶&#xff0c;则另一端被称为栈底&#xff0c;而栈内的数据遵循后进后出&#xff0c;先进后出的原则 入栈&#xff1a;栈的插入操作被称为进栈、入栈、压栈&a…

blockchain实现遇到的问题

区块链分叉 v1114 : 基于python socket 创建TCP server&#xff0c;以中心化的形式暂时实现区块链的状态同步 C:\Users\vin0sen>nc 192.168.137.1 9000 Enter a new data: 111 {"index": 1, "timestamp": "2024-11-14 15:28:53.173112", &quo…

Shell脚本4 -- 数学运算

声明&#xff1a; 本文的学习内容来源于B站up主“泷羽sec”视频【shell &#xff08;3&#xff09;脚本参数传递与数学运算】的公开分享&#xff0c;所有内容仅限于网络安全技术的交流学习&#xff0c;不涉及任何侵犯版权或其他侵权意图。如有任何侵权问题&#xff0c;请联系本…

2025年入门深度学习或人工智能,该学PyTorch还是TensorFlow?

随着2025应用人工智能和深度学习技术的举世泛气&#xff0c;还在迷茫于该选择哪个深度学习框架吗&#xff1f;PyTorch和TensorFlow是并立于深度学习世界两座巨塔&#xff0c;但是越来越多人发现&#xff0c;在2025年&#xff0c;PyTorch似乎比TensorFlow更为流行和被接受。下面…

区块链智能合约开发:全面解析与实践指南

随着区块链技术的不断发展&#xff0c;智能合约作为其中的核心组成部分&#xff0c;已经在多个领域展现出了巨大的潜力。智能合约不仅是去中心化应用&#xff08;DApp&#xff09;和去中心化金融&#xff08;DeFi&#xff09;的基础&#xff0c;也是推动区块链技术应用广泛发展…

跨平台WPF框架Avalonia教程 十一

控件类型 如果您想创建自己的控件&#xff0c;Avalonia中有三个主要的控件类型。首先要做的是选择最适合您使用场景的控件类型。 用户控件(User Controls)​ UserControl是创建控件的最简单方法。这种类型的控件最适合特定于应用程序的“视图”或“页面”。UserControl的创建…

MATLAB深度学习(二)——如何训练一个卷积神经网路

2.1 基本概念 从数学的角度看&#xff0c;机器学习的目标是建立输入和输出的函数关系&#xff0c;相当于 y F&#xff08;x&#xff09;的过程。F&#xff08;x&#xff09;就是我们所说的模型&#xff0c;对于使用者来说&#xff0c;这个模型就是一个黑箱&#xff0c;我们不知…

VSCode 常用的快捷键

Visual Studio Code (VSCode) 提供了丰富的快捷键来提高开发效率。 是常用的 VSCode 快捷键&#xff0c;按功能分类&#xff1a; 1. 基础编辑 Ctrl C / Ctrl V / Ctrl X&#xff1a;复制、粘贴、剪切当前选中的文本。Ctrl Z / Ctrl Y&#xff1a;撤销和重做操作。Ctrl …