前几天在朋友圈看到关于排序算法的文章,上周周末有时间重新的研究了关于快排的思想和算法。
直接进入正题吧,快排算法的思想主要是分两步:
1.使用空间复杂度为1的方法将一堆数中的某个元素找到自己的位置,并且保证左边的数比自己小(大),右边的数比自己大(小);
2.将这个堆数左边所有的数再次当做那堆数放到上面1的方法中,重复,直到代入的这堆数完全有序,完成之后再将将右边所有的数当做那堆数放到上面的1中直到代入的这堆数完全有序。
就随便拿网上的一个算法来说[1]:
初始数据为 :[6,10,13,5,8,3,2,11] 以6为第一步的某个元素,完成第一步之后 [2,5,3],[6],[8,13,10,11],第二步则是将[2,5,3],作为一个数组放到方法1中,[2,5,3]排序完成之后,再将[8,13,10,11]当做一个数组。
第二步很简单,是典型的递归。
个人觉得这个排序算法比较牛的是第一步,现在我们来想一个如果给你一个数组让你找到第一个数的位置(即如果这个数组有10个,它是第五大,这个时候他的位置就是4),并且保证前面的这个数前面的数都比他小(大),后面的数都比他大(小)。
如果在不限定空间复杂度的话这个算法还是有很多种的,比如我可以先遍历一下这个数组s[],在遍历的过程中将比这个数大的放到一个数组中a[],将这个数小的放到一个数组中b[],等遍历完成之后再将a[],s[0],b[]这三个数组重新合成一个数组;还可以再申请一个数组t[],先将s[0]放到最后一个,如果再去遍历s,在遍历过程中对s[0]的位置进行调整,并记录s[0]所在的位置,最后也能保证在s[0]前面的数都比它小(大),在s[0]后面的数都比他大。因为这个算法比较简单,我就不举例说明了。
但是上面的算法都是额外申请了内存的,空间复杂度不为1的。
现在我们来看下官宣的快排是怎么做的:
依然以上面的数为例:[6,10,13,5,8,3,2,11],拿6做比较,如果先从后面开始比较,如果找到比6小的2,则
将 6和它换个位置,再从另一侧开始,这样做的目的就是保证比较过的数能够放在合适的位置(放在左边或者放在右边),而保证等再一次回到后面这侧做比较的时以及比较过的数11就不比较了,从3开始比较,这样就保证了之前比较的数没有被破坏顺序,等第一轮完成了之后,6就找到了其对应的位置。
.
1. https://www.cnblogs.com/cylee025/archive/2011/05/11/2043714.html