假设我们现在对“6  1  2 7  9  3  4  5 10  8”这个10个数进行排序。首先在这个序列中随便找一个数作为基准数(不要被这个名词吓到了,就是一个用来参照的数,待会你就知道它用来做啥的了)。为了方便,就让第一个数6作为基准数吧。接下来,需要将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,类似下面这种排列。
3  1  2 5  4  6  9 7  10  8
在初始状态下,数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于6,右边的数都大于等于6。想一想,你有办法可以做到这点吗?
给你一个提示吧。请回忆一下冒泡排序,是如何通过“交换”,一步步让每个数归位的。此时你也可以通过“交换”的方法来达到目的。具体是如何一步步交换呢?怎样交换才既方便又节省时间呢?先别急着往下看,拿出笔来,在纸上画画看。我高中时第一次学习冒泡排序算法的时候,就觉得冒泡排序很浪费时间,每次都只能对相邻的两个数进行比较,这显然太不合理了。于是我就想了一个办法,后来才知道原来这就是“快速排序”,请允许我小小的自恋一下(^o^)。
方法其实很简单:分别从初始序列“6  1  2 7  9  3  4  5 10  8”两端开始“探测”。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换他们。这里可以用两个变量i和j,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。刚开始的时候让哨兵i指向序列的最左边(即i=1),指向数字6。让哨兵j指向序列的最右边(即j=10),指向数字8。

首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,这一点非常重要(请自己想一想为什么)。哨兵j一步一步地向左挪动(即j--),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。

现在交换哨兵i和哨兵j所指向的元素的值。交换之后的序列如下。

6  1  2  5  9 3  4  7  10  8

到此,第一次交换结束。接下来开始哨兵j继续向左挪动(再友情提醒,每次必须是哨兵j先出发)。他发现了4(比基准数6要小,满足要求)之后停了下来。哨兵i也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。此时再次进行交换,交换之后的序列如下。
6  1  2 5  4  3  9  7 10  8
第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的序列如下。
3  1 2  5  4  6  9 7  10  8

到此第一轮“探测”真正结束。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。
OK,解释完毕。现在基准数6已经归位,它正好处在序列的第6位。此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是“3  1 2  5  4”,右边的序列是“9  7  10  8”。接下来还需要分别处理这两个序列。因为6左边和右边的序列目前都还是很混乱的。不过不要紧,我们已经掌握了方法,接下来只要模拟刚才的方法分别处理6左边和右边的序列即可。现在先来处理6左边的序列现吧。
左边的序列是“3  1  2 5  4”。请将这个序列以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。好了开始动笔吧。
如果你模拟的没有错,调整完毕之后的序列的顺序应该是。
2  1  3  5  4
OK,现在3已经归位。接下来需要处理3左边的序列“2 1”和右边的序列“5 4”。对序列“2 1”以2为基准数进行调整,处理完毕之后的序列为“1 2”,到此2已经归位。序列“1”只有一个数,也不需要进行任何处理。至此我们对序列“2 1”已全部处理完毕,得到序列是“1 2”。序列“5 4”的处理也仿照此方法,最后得到的序列如下。
1  2  3 4  5  6 9  7  10  8
对于序列“9  7  10  8”也模拟刚才的过程,直到不可拆分出新的子序列为止。最终将会得到这样的序列,如下。
1  2  3 4  5  6  7  8 9  10
到此,排序完全结束。细心的同学可能已经发现,快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。下面上个霸气的图来描述下整个算法的处理过程。

快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。
#include <stdio.h>
int a[101],n;//定义全局变量,这两个变量需要在子函数中使用
void quicksort(int left, int right) {int i, j, t, temp;if(left > right)return;temp = a[left]; //temp中存的就是基准数i = left;j = right;while(i != j) { //顺序很重要,要先从右边开始找while(a[j] >= temp && i < j)j--;while(a[i] <= temp && i < j)//再找右边的i++;       if(i < j)//交换两个数在数组中的位置{t = a[i];a[i] = a[j];a[j] = t;}}//最终将基准数归位a[left] = a[i];a[i] = temp;quicksort(left, i-1);//继续处理左边的,这里是一个递归的过程quicksort(i+1, right);//继续处理右边的 ,这里是一个递归的过程
}
int main() {int i;//读入数据scanf("%d", &n);for(i = 1; i <= n; i++)scanf("%d", &a[i]);quicksort(1, n); //快速排序调用//输出排序后的结果for(i = 1; i < n; i++)printf("%d ", a[i]);printf("%d\n", a[n]);return 0;
}


 

快速排序(过程图解)相关推荐

  1. JAVA快速排序过程图解(10步之内看懂)

    废话不多说,下面图解说明快速排序算法,并附上JAVA代码 假如我们对"3 4 7 2 4 3 1 4 5 9"这10个数进行快速排序 第1步,先设置一个基准数,这个基准数可以是任意 ...

  2. activiti-explorer mysql_Activiti explorer.war示例工程使用过程图解

    Activiti explorer.war示例工程使用过程图解 发布时间:2020-09-03 07:26:22 来源:脚本之家 阅读:98 作者:yaominghui 工作流主要解决的主要问题是:为 ...

  3. jenkins配置python脚本参数_jenkins配置python脚本定时任务过程图解

    这篇文章主要介绍了jekins配置python脚本定时任务过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 2.下载安装包后直接运行,进行选择 ...

  4. Java05-day05【方法(概述、调用过程图解)、带参方法、带返回值方法、重载、方法参数传递(基本类型、引用类型)】

    java零基础入门到精通(2019版)[黑马程序员] 视频+资料:[链接:https://pan.baidu.com/s/1MdFNUADVSFf-lVw3SJRvtg   提取码:zjxs] &qu ...

  5. win7硬盘安装过程图解

    win7硬盘安装过程图解 我都红字还放大了"根目录",可为什么还有人要放到文件夹里呢?我还怕有人不知道什么叫根目录,还专门用通俗的,小学生都能理解的话解释了什么叫根目录,可是还是有 ...

  6. linux中python安装_linux环境下的python安装过程图解(含setuptools)

    这里我不想采用诸如ubuntu下的apt-get install方式进行python的安装,而是在linux下采用源码包的方式进行python的安装. 一.下载python源码包 打开ubuntu下的 ...

  7. python实现数据恢复软件_pyinstaller还原python代码过程图解

    这篇文章主要介绍了pyinstaller还原python代码过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 pyinstaller 的作用就 ...

  8. 计算机网络封装过程图,网络传输过程是怎样的?网络数据传输的过程图解

    下面要给大家讲到的是一个非常基础的问题,大家对于网络传输过程都了解吗?你知道具体的过程是怎样的吗?下面一起仔细的了解一下吧! 一.过程图解 首先我们来看一个非常简单的过程图: 在数据链路层有一个标识, ...

  9. 安装操作系统的过程图解

    安装操作系统的过程图解 这段时间因为突然对安装操作系统比较感兴趣,所以,就萌生了熟悉安装单操作系统.多操作系统的想法,当然,也凭任性的坚持付诸了行动,并写成了比较挫的安装图解.就把这些贴出来吧,望看了 ...

  10. python调用os.system启动anaconda环境_在Mac中PyCharm配置python Anaconda环境过程图解

    在 python 开发中我们最常用的IDE就是PyCharm,有关PyCharm的优点这里就不在赘述.在项目开发中我们经常用到许多第三方库,用的最多的命令就是pip install 第三方库名 进行安 ...

最新文章

  1. centos7离线安装metasploit
  2. left join 与left outer join的区别
  3. 唯品会API网关设计与实践--转
  4. stdthread(6)并发mutex
  5. 【深度学习】深度学习在视觉搜索和匹配中的应用
  6. c#简单自定义异常处理日志辅助类
  7. 通过粘性仙人掌基元进行延迟加载和缓存
  8. win7下的nginx小demo
  9. java 如何导出json文件_java导出json格式文件的示例代码
  10. orm2 中文文档 8. 聚合
  11. Atitit v2 工作计划与工作日志推荐格式markdown 与模板 attilax 总结
  12. 计算机软件版本号是什么意思,带你深入了解解密Windows系统版本和版本号
  13. 深入理解JVM & G1 GC
  14. 大一acmer日常记录day15
  15. 小提琴1234567位置图解_1秒找到小提琴上的每个调音阶
  16. vue2和vue3 的 keep-alive的用法
  17. 电脑录屏怎么录?超详细的录屏教程来了
  18. Polar码(2)- Polar编码
  19. bat 批处理 B站缓存视频转成 .mp4格式
  20. Educational Codeforces Round 140 (Rated for Div. 2)题解

热门文章

  1. linux local root exploit,Linux非交互环境下本地提权思路与反思 linux localroot exploit
  2. 花猫c语言,C语言实现小猫钓鱼游戏 - 技术经验 - W3xue
  3. 零成本、零流量,我是如何空手反套白狼?
  4. Word2010经常莫名其妙无法撤销
  5. 关于农历闰月年份的口诀
  6. oracle同义词6,Oracle同义词
  7. oracle中同义词作用,Oracle同义词创建及其作用
  8. Python 流程控制
  9. linux全角半角切换快捷键,切换中英文标点快捷键,全角半角之间的转换快捷键
  10. Bada学习-SDK的安装