快速排序:
输入:乱序n长数组
输出:排序好的n长数组
时间复杂度:O(nlogn)
空间复杂度:O(1)
快速排序的基本逻辑是这样的:每次随机挑选一个数组的元素,作为“枢轴”,然后扫描数组中其他的所有元素,将小于枢轴的,排列在枢轴的左侧,大于枢轴的,排列在枢轴的右侧。然后再分别对枢轴左右两侧的部分数组进行快速排序(这是一个递归的逻辑),这样,当递归运算“触底”后(每次需要快排的部分数组中只有一个元素),逐层返回,就最终得到排好序的数组了。
举例说,需对数组[6,5,3,1,8,7,2,4]进行快排,不失一般性,我们选择数组的第一个元素,这里是6,作为枢轴,随后扫描[5,3,1,8,7,2,4]部分,那么经过调整后,数组变为[4,5,3,1,2,6,8,7],6之前的元素都比6小,6之后的都比6大。然后再用快排分别处理[5,3,1,4,2]部分和[7,8]部分。需注意的一点是经过第一次快排,其实是确定了枢轴元素在排好序的整个数组中的位置。
我们详细看一下算法细节:排序L = [6,5,3,1,8,7,2,4]
(1) 选定6作为枢轴
(2) 5 < 6,count = 1 -> 5与L[1]交换位置,这里相当于不变
(3) 3 < 6,count = 2 -> 3与L[2]交换位置,这里相当于不变
(4) 1 < 6,count = 3 -> 1与L[3]交换位置,这里相当于不变
(5) 8 > 6 -> 不作为
(6) 7 > 6 -> 不作为
(7) 2 < 6,count = 4 -> 2与L[4]交换位置,这里相当于2与8交换位置 -> L = [6,5,3,1,2,7,8,4]
(8) 4 < 6,count = 5 -> 4与L[5]交换位置,这里相当于4与7交换位置 -> L = [6,5,3,1,2,4,8,7]
(9) 最后一步,将枢轴和现在count所指的元素交换位置:6与L[5]交换 -> L = [4,5,3,1,2,6,8,7]
同理,再分别对6左边的部分和6右边的部分进行快排,即可得到排序的数组。
输入:乱序n长数组
输出:排序好的n长数组
时间复杂度:O(nlogn)
空间复杂度:O(1)
快速排序的基本逻辑是这样的:每次随机挑选一个数组的元素,作为“枢轴”,然后扫描数组中其他的所有元素,将小于枢轴的,排列在枢轴的左侧,大于枢轴的,排列在枢轴的右侧。然后再分别对枢轴左右两侧的部分数组进行快速排序(这是一个递归的逻辑),这样,当递归运算“触底”后(每次需要快排的部分数组中只有一个元素),逐层返回,就最终得到排好序的数组了。
举例说,需对数组[6,5,3,1,8,7,2,4]进行快排,不失一般性,我们选择数组的第一个元素,这里是6,作为枢轴,随后扫描[5,3,1,8,7,2,4]部分,那么经过调整后,数组变为[4,5,3,1,2,6,8,7],6之前的元素都比6小,6之后的都比6大。然后再用快排分别处理[5,3,1,4,2]部分和[7,8]部分。需注意的一点是经过第一次快排,其实是确定了枢轴元素在排好序的整个数组中的位置。
我们详细看一下算法细节:排序L = [6,5,3,1,8,7,2,4]
(1) 选定6作为枢轴
(2) 5 < 6,count = 1 -> 5与L[1]交换位置,这里相当于不变
(3) 3 < 6,count = 2 -> 3与L[2]交换位置,这里相当于不变
(4) 1 < 6,count = 3 -> 1与L[3]交换位置,这里相当于不变
(5) 8 > 6 -> 不作为
(6) 7 > 6 -> 不作为
(7) 2 < 6,count = 4 -> 2与L[4]交换位置,这里相当于2与8交换位置 -> L = [6,5,3,1,2,7,8,4]
(8) 4 < 6,count = 5 -> 4与L[5]交换位置,这里相当于4与7交换位置 -> L = [6,5,3,1,2,4,8,7]
(9) 最后一步,将枢轴和现在count所指的元素交换位置:6与L[5]交换 -> L = [4,5,3,1,2,6,8,7]
同理,再分别对6左边的部分和6右边的部分进行快排,即可得到排序的数组。
Python 代码如下:
def quick_sort(aList):
first = 0
# 设定需要扫描的数组首尾位置
last = len(aList) - 1
# 改变参数的快速排序函数
aList = quick_sort_helper(aList, first, last)
return aList
def quick_sort_helper(aList, first, last):
# 这种情况说明扫描的数组部分只有一个元素了,直接返回
# 需要注意的是,原地排序没有真正意义上分割数组
# 只是对数组的不同部分做交换位置操作
# 所以“触底”后返回的是整个数组
if first >= last:
return aList
# 建立“枢轴”,不失一般性,令枢轴为扫描部分的第一个元素
pivot = aList[first]
# 计数,求出比枢轴小的元素的个数(也就是需要调整到的位置索引)
count = first
for index in range(first + 1, last + 1):#扫描
if aList[index] < pivot:
count += 1
# 交换位置
aList[index], aList[count] = aList[count], aList[index]
aList[count], aList[first] = aList[first], aList[count]
quick_sort_helper(aList, first, count - 1)
# 递归运算
quick_sort_helper(aList, count + 1, last)
return aList