计算机快速排序举例,3. 快速排序
快速排序(Quick Sort)与冒泡排序均为交换类排序。快排是对冒泡排序的一种改进。由于关键字的比较和交换是跳跃进行的,因此,快速排序是一种不稳定的排序方法。
0. 序
1. 冒泡排序
2. 快速排序
2.1 基本思想
2.2 一趟快速排序(一趟划分)
2.3 过程
2.4 实现
2.5 复杂度分析
2.5.1 时间复杂度(包含证明)
2.5.2 空间复杂度
0. 序
快速排序算法最早由图灵奖获得者Tony Hoare设计出来的,他在形式化方法理论以及ALGOL60编程语言的发明中都有卓越的贡献,是上世纪最伟大的计算机科学家之一。
快速排序被列为20世纪十大算法之一。
1. 冒泡排序
假设在排序过程中,记录序列R[1...n] 的状态为:
2. 快速排序
快速排序也是通过不断比较和移动交换来实现排序的,只不过它的实现,增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少了总的比较次数和移动交换次数。
2.1 基本思想
通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后分别对这两部分继续进行排序,直到整个序列有序。
2.2 一趟快速排序(一次划分)
目标:找一个记录,以它的关键字作为“枢纽”,凡其关键字小于枢纽的记录均移动至该记录之前,反之,凡关键字大于枢纽的记录均移动至该记录之后。
设 R[s] = 52 为枢纽
将R[high].key 和枢纽的关键字进行比较,要求R[high].key≥ 枢纽的关键字
将R[low].key 和枢纽的关键字进行比价,要求R[low].key≤ 枢纽的关键字
可见,经过“一次划分”,将关键字序列:
52, 49,80,36,14,58,61,97,23,75
调整为: 23,49,14,36, (52),58, 61,97, 80,75
在调整过程中,设立了两个指针:low 和 high,它们的初值分别为:s 和t
之后逐渐减小high,增加low,并保证R[high].key≥52,和R[low].key≤52,否则进行记录的“交换”。
2.3 过程
首先对无序的记录序列进行“一次划分”,之后分别对分割所得两个子序列“递归”进行快速排序。
2.4 实现
//快速排序 O(nlogn) --->逆序O(n^2)//调用QSort(1, n) 待排记录index = 1 ... n
public int[] QSort(int low, inthigh){if(low
QSort(low, p-1);
QSort(p+1, high);
}returnneedSort;
}private int Partition(int low, inthigh){
needSort[0] =needSort[low];while(low = needSort[0]) high--;
needSort[low]=needSort[high];while(low < high && needSort[low] <= needSort[0]) low++;
needSort[high]=needSort[low];
}
needSort[low]= needSort[0];returnlow;
}
2.5 复杂度分析
2.5.1 时间复杂度
① 在最优情况下,Partition每次都划分得很均匀,如果排序n个关键字,其递归树(见2.5.2)的深度就为
,即仅需递归log2n次,需要时间为T(n)的话,第一次Partition应该是需要对整个数组扫描一遍,做n次比较。然后,获得的枢纽将数组一分为二,那么各自还需要T(n/2)的时间(注意是最好情况,所以平分两半)。于是不断地划分下去,我们就有了下面的不等式推断。
T(n) ≤2T(n/2) + n, T(1) = 0
T(n) ≤2( 2T(n/4) + n/2 ) + n = 4T(n/4) + 2n
T(n) ≤4( 2T(n/8) + n/4 ) + 2n = 8T(n/8) + 3n
...
T(n) ≤nT(1) + (log2n) * n = O(nlogn)
不知道为什么是“≤”而不是“=”? 待补充
也就是说,在最优的情况下,快速排序算法的时间复杂度为O(nlogn)。
② 在最坏情况下,待排序的序列为正序或逆序,每次划分只得到一个比上一次划分少一个记录的子序列,注意另一个为空。如果递归树画出来,它是一颗斜树。此时需要执行n-1次递归调用,且第i次划分需要经过n-i次关键字的比较才能找到第i个记录,也就是枢纽的位置,因此比较次数为
,最终其时间复杂度为O(n2)。
③ 平均的情况,设枢纽的关键字应该在第k的位置(1≤k≤n),每个位置的概率相同,均为1/n,那么:
数学归纳法可证明,其数量级为O(nlogn)。 待补充
通常,快速排序被认为是在所有同数量级O(nlogn) 的排序方法中,其平均性能是最好的。但是,若待排记录的初始状态为按关键字有序或基本有序时,快速排序将蜕化为冒泡排序,其时间复杂度为O(n2)。
为避免出现这种情况,需在进行一次划分之前,进行“预处理”,即:先对R(s),key,R(t).key和R[└(s+t)/2┘].key,进行相互比较,然后取关键字为“三者之中”的记录为枢纽记录。
2.5.2 空间效率
举例:
快速排序的递归过程可用生成一颗二叉树形象地给出,下图对应上面例子递归调用过程的二叉树。
快速排序是递归的,每层递归调用时的指针和参数均要用栈来存放,递归调用层数与上述二叉树的深度一致。因而,存储开销在理想情况下为O(log2n),即树的高度,其空间复杂度也就为O(logn);在最坏情况下,需要进行n-1次递归调用,即二叉树是一个单链,为O(n);平均情况,空间复杂度也为O(logn)。
注意,由于关键字的比较和交换是跳跃进行的,因此,快速排序是一种不稳定的排序方法。
参考:
上课ppt
《大话数据结构》程杰著 清华大学出版社,2011.6(2017.6 重印)
计算机快速排序举例,3. 快速排序相关推荐
- python快速排序解析_快速排序python实现总结
算法 数据结构 快速排序python实现总结 背景:数据结构与算法是IT相关的工程师一直以来的基础考察重点,很多经典书籍都是用c++或者java来实现,出于对python编码效率的喜爱,于是取sear ...
- 这是一个php中快速排序字母,php 快速排序
快速排序是以其中一个数为比较标准,其他比较的数分块处理,应用递归按相同想法处理数据 比如:4 3 6 2 1 7 8 以4为比较对象 排序为 3 2 1 6 7 8 左边为 3 2 1 右边 为 6 ...
- java jdk实现快速排序_Java实现快速排序过程分析
快速排序过程 没有既不浪费空间又可以快一点的排序算法呢?那就是"快速排序"!光听这个名字是不是就觉得很高端呢. 假设我们现在对"52 39 67 95 70 8 25 5 ...
- 算法-排序-快速排序(包含多种快速排序)
快速排序 特点:原址排序,最坏的时间复杂度O(n^2) 平均时间复杂度O(nlgn) 比归并排序系数常数项小 不稳定 底部有最坏时间复杂度为Ω(nlgn)的快速排序地址 void quick_sort ...
- 排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序)
排序上 排序上 交换类排序 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动. ...
- php快速排序实现代码,快速排序的算法php实现
function qsort(&$arr) { _quick_sort($arr, 0, count($arr) - 1); } /** * 采用递归算法的快速排序. * * @param a ...
- c语言双向链表 快速排序,双向链表的快速排序(swift版本)
面试经常会被问到的单向链表的快速排序or双向链表的快速排序,现在用swift写了一个双向链表的快速排序,直接上代码 获取源码 //初始化 var linkList = LinkList() linkL ...
- python列表快速排序_python 实现快速排序
一.快排思想 快速排序可以理解为是对冒泡排序的一种改进,把一组数,按照初始选定的标杆(参照数), 分别从两端开始排序,左端'i'只要小于标杆(参照数)的数,右端'j'只要大于标杆(参照数)的数, i- ...
- [转载] 数组快速排序python_python实现快速排序
参考链接: Python中的快速排序Quicksort 最近在公司的工作内容发生变化,短期内工作量变少了,这也让我有时间整理一些日常学习和工作中的收获或思路.所以申请了博客,并打算持续更新. 快速排序 ...
最新文章
- 合肥天鹅湖万达广场机器人_万达王健林再考察合肥!瞄准政务、高新,年末合肥楼市出现区域分化!...
- go 清空文件内容_玩转Go单元测试,你只需要掌握这5点
- linux安装jetty部署war包,jetty部署war包
- 流量银行与阿里联手放大招 1毛钱换1块钱
- 由于更换了java版本,Eclipse启动时报错:JRE or JDK must be available in order to run Eclipse
- 深度解密 Go math/rand
- 世界第一台电脑_电脑的诞生与发展
- 抓住好资产,让你赚一辈子
- ios ffmpeg+libx264
- 作为程序员的我,接私活有错么?
- python实现递归和非递归求两个数最大公约数、最小公倍数
- 对象复制语意学(Object Copy Semantics)
- 怎么用dos系统进入服务器,怎么进入dos_如何进入dos的方法(图文介绍)
- matlab subs eval,【荐】MATLAB求解符号表达式数值的方法:subs函数
- 【聚英云农】无线节水灌溉系统应用智慧农业
- word07如何插入和删除分节符
- switch日版有中文吗_原神Switch日版可以玩吗
- 苹果遭遇史上最严厉的泄密:自家的iOS源代码居然泄漏了
- cocos create tween
- shell输出毫秒_linux shell 获取毫秒数 计时