博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
快速排序---左右互搏(换)术
阅读量:4170 次
发布时间:2019-05-26

本文共 1289 字,大约阅读时间需要 4 分钟。

1. 思路

快速排序基于这样一种想法:给定一个序列,完之后,数据一定在左侧,数据大的一定在右侧。根据这一特性,随机的在序列中取一个数k,只需要把比这个的数据换到右侧,这个数小的数据换到左侧,就完成了一次排序。然后以k为中心,将数组分成两部分再分别对这部分如上操作直到排完成个序列这种策略很像老顽童的左右互搏术,或者乾坤大挪移之类的功法,说了就是来回倒腾。

接下来我们简单描述一下排序过程

a. 对以下数组取中间数6,我们需要两个索引ij。其中i从左向右偏移j从右向左偏移。初始化状态下图

 

b. j[j]<6,所以j不动,而i需要连续索引直到i=3位置碰到7.如下

 

c. 互换[i][j]位置,如下

 

d. ji继续索引前行j停在8位置i停到4位置

 

e. [i][j]互换结果

 

f. 继续

 

g. 结果

 

h. 直到 ij相遇,既i==j

 

最终

 

由此我们得到了一个大致有序的序列,并且以6中点,将数组分成了两部分。我们可以分别对两个数组进行如上操作,递归整个数组处理完毕。这里再不赘述余下部分。

注:整个过程实际上基于两个目的:第一,大踏步互换位置;第二,确定k的最终位置。

2.代码片段

A. 外部调用接口

 

B. 排序核心逻辑

 

C. 执行过程

 

绿色本次选中的数,红色为出现交换的数,黑色位置不变

3.时间复杂度分析

我们这里不用复杂的数据逻辑来证明,给出一个感官上的认识。如果你对数学方面的证明非常好奇,可以参考这篇。

最好情况数组每次进行折半排序折半的两个数组是均匀的。这时候层数为logN折半过程就是把线性N化成logN过程),对于每一层,比较次数依然我N,所以整个排序的时间复杂度O(NlogN).

   最坏的情况。假设每次取到的都是最的或者最大的那么每次折半数组被分成了0长度N长度两个数组,有一个数组折半失效了,这个时候的时间复杂度为O(N2)

4.总结与思考

    如果大家熟悉归并排序,就会发现这两个排序貌似有点什么关系,二者不太一样。实际上他们的思想是相似又相反的。他们都是源于思想采用了递归。但是合并算法是分解后排序,而快速排序是先排序会分解他们的过程是相反的。

快速排序是不稳定的排序算法每次取值对他的性能影响非常大。如果能够每次取到中间值那么算法性能将会得到改善典型的优化方法之一就是“三值取中序列的第一个值最后一个值以及中间值,这三个值中找出中间值做为参考值来进行每一次排序。这种方法可以避免取到极值情况(最大值,最小值)。还有一种优化方法叫做小区间优化。根据快速排序过程,我们不难想象,经过若干次分解后,得到的各个小数组是大致有序的。如果大家熟悉的特性就会马上意识到,这种大致有序的小数组正是插入排序的最爱所以当数组被到分解到一定程度一般建议为5---13,选择插入排序能够极大的提升整体性能。

没有一个万能的算法能够适应所有情况,我们能做的就是根据已知序列的特点以及各个算法的特性来进行合理的组合,最终得到可接受的预期值。

你可能感兴趣的文章
分析若干没面试机会和没体现实力的简历
查看>>
用python的matplotlib和numpy库绘制股票K线均线
查看>>
以互联网公司的经验告诉大家,架构师究竟比高级开发厉害在哪?
查看>>
GanttProject 使用的控件第三方包:jdnc-modifBen.jar
查看>>
ps、grep和kill联合使用杀掉进程
查看>>
openfire中的mina框架使用
查看>>
去掉Windows Messager的自动登录
查看>>
dspace可以检索中文了
查看>>
利用Eclipse编辑中文资源,配置文件
查看>>
将中文转为unicode 及转回中文函数
查看>>
《程序员》专访金蝶:是谁不相信国产软件?
查看>>
debian的gnome下的xmms乱码解决方案
查看>>
python切片操作
查看>>
python 中的split()函数和os.path.split()函数
查看>>
python 矩阵转置
查看>>
python 使用zip合并相邻的列表项
查看>>
python iter( )函数
查看>>
Python 迭代器(iterator)
查看>>
Python enumerate类
查看>>
leetcode 99 Recover Binary Search Tree (python)
查看>>