首先说一点官方的话,快排思想什么的
思想:选取一个元素做为关键数据(一般选择第一个元素),然后将所有比他小的数都放在他前面,所有大于等于他的数都放到他的后边,作为一个快速排序的过程。
当然这个思想要是看不懂,也不要问我,因为我也没看。
个人总结的片面的快排思想就是:把基准值(也就是key值)移动到中间,这个中间就是左边都是小于key值的,右边都是大于key值的,然后key值左边的重新递归,key值右边的值重新递归,这就是快速排序。
那么我们举个栗子:
a = [5,4,3,6,2,7,1]
首先我们要确定三个值:
left = 0 这个是左边的指针,默认是a列表的下标0
right = 6 这个是列表右边的指针,默认设置为a列表最后一个小标6
key = 5 这个就是咱们设置的基准值,用于作比较用的
第一轮:key 和 a[right](也就是key和右指针对应的值去作比较),那么谁大就把谁放在右边,key = 5, a[6] = 1 所以需要调换 位 置比较关键的一点,在交换位置的同时,也要交换比较方向,所以通过交换后的列表为
[1,4,,3,6,2,7,5]
第二轮:此时key = 5 右指针用过一次,因为第一轮后要改变比较方向,所以key又要和左指针做比较,左指针的初始值为a[0]也 就是1。因为是从小到大大排序,所以1本身是小于5的,所以位置不用改变,位置不变,那么方向就不用变,所以第二 轮列表保持不变
[1,4,,3,6,2,7,5]
第三轮 :由于第二轮的时候位置没有发生改变,所以方向就不变,于是key值继续和左指针的第二位做比较,也就是列表下标为 1 的值做比较,key = 5 a[1] = 4 key值依旧大于左指针指向的值,所以列表依旧保持
[1,4,,3,6,2,7,5]
第四轮:由于第三轮位置并没有发生改变,所以方向也依旧不变,于是key值继续和左指针的第三位做比较,也就是列表下表为2 的值做比较, key = 5 a[2] = 3 key值依旧大于左指针指向的值,所以列表依旧保持
[1,4,,3,6,2,7,5]
第五轮:由于第四轮位置并没有发生改变,所以方向也依旧不变,于是key值继续和左指针的第四位做比较,也就是列表下表为3的值作比较,key = 5, a[3] = 6 key的值小于左指针的值,所以位置发生发改变,方向也随之发生改变,此时列表为
[1,4,3,5,2,7,6]
第六轮:由于无论位置发生改变,所以比较方向也随之发生改变,key值就要和右指针做比较,因为右指针已经在第一轮的时候 用过一次了,所以这次再和右指针作比较,就应该是a[5] = 7 关键值key=5,两个数做比较,发现key < 右指针,所以保 持 不变,此时列表为
[1,4,3,5,2,7,6]
第七轮:由于位置没有发生改变,所以方向也不用改变,key值就继续和右指针的上一位做比较,也就是key = 5, a[4] = 2 此时 key大于右指针,于是位置发生改变,此时列表为
[1,4,3,2,5,7,6]
到目前为止,我们发现,关键值5左边的数都比5小了,右边的值也都比5大,(虽然是乱序)于是我们把5左边的这些值再重新按照初始排序那样比较一次,5右边的数重新按照初始值比较一次,知道最后的顺序为12,3,4,5,6,7为止,这一步也就是咱们快排中的递归,记下来我们就看看代码
def quicksort(l,start,end):
left = start
right = end
#结束递归的条件,最终相比较需要列表里len的长度为1才能结束
if left < right:
key = l[left]
#左右指针不重合的情况
while left < right:
#如果列表右边的数,比基准数大或相等,则前移一位直到有比基准数小的数出现
while left < right and l[right] >= key:
right -= 1
l[left],l[right] = l[right],l[left]
#如果列表右边的数,比基准数小或者相等,则交换位置
while left < right and l[left] <= key:
left += 1
l[left],l[right] = l[right],l[left]
quicksort(l,start,left - 1)
quicksort(l,right + 1,end)
return l
l = [3,9,2,2,1,6,5,5,4,9,8,3]
print(quicksort(l,start=0,end=len(l)-1))
关键的一点,如果左右两边数字出现相等的情况,就不去操作,因为数值一样,再去操做就等于多一个操作,影响效率