什么是快速排序
听说这是大部分程序员最常用的排序算法,程序员做事就是有效率高,质量好而且快。(好像所有职业要求都是这样的)。快速排序主要是依靠一个数轴,如果大于数轴的就往左放,小于数轴就往右放。
快速排序的思路
核心思想:在数列中选取一个数轴,大于数轴往右放,小于往左放
用[5,4,3,6,1,2]举例子。
第一步:在数列中随机选取一个数字当为数轴(为方便起见,选择数列首项 6)
第二步:定义两个指针(此指针非C,C++中的指针,仅仅是数列的浮标)
分别在左边第一项(含第零项)和右边末尾项 2。
第三步:规则:如果右指针所指向的数字 < 数轴,则向右移动左指针,否则一直向左移动右指针。直到发现左指针所指向的数字 > 数轴,交换当前左右指针的元素。重复执行上述直到左指针碰到右指针,将当前左右指针指向的数字与数轴的数字互换
[5,4,3,6,1,2]
数轴:5
左指针:5
右指针:2
右指针的数字2 < 数轴 5。移动左指针。
第四步:左指针移动
数轴:5
左指针:4
右指针:2
按照规则,继续移动
第五步:左指针移动
数轴:5
左指针:3
右指针:2
按照规则,继续移动
第六步:左指针移动
数轴:5
左指针:6
右指针:2
第七步:左指针指向的数字 6 > 数轴5,交换当前左右指针所指向的数值
[5,4,3,2,1,6]
数轴:5
左指针:2
右指针:6
第八步:移动有右指针
数轴:5
左指针:2
右指针:1
第九步:右指针指向的值 < 数轴的值5
数轴:5
左指针:2
右指针:1
第十步:移动左指针
数轴:5
左指针:1
右指针:1
第十一步:移左右指针相同,交换数轴 5 和左右指针的数值 1
数轴:5
左指针:1
右指针:1
[1,4,3,2,5,6]
接着将起始点设为0,终止点设为当前左右指针的值 以及起始点为当前左右指针的值+1,终点设为数列的末尾。
[1,4,3,2] 与 [5,6]
对数列[1,4,3,2]执行上述操作
初始条件
数轴:1
左指针:1
右指针:2
第一步:右指针的数值 > 数轴 右指针移动
数轴:1
左指针:1
右指针:3
第二步:右指针的数值 > 数轴 右指针移动
数轴:1
左指针:1
右指针:4
第三步:右指针的数值 > 数轴 右指针移动
数轴:1
左指针:1
右指针:1
第四步:左右指针相遇,将数轴的值与当前左右指针的值交换 还是1
数轴:1
左指针:1
右指针:1
[1,4,3,2]
检测左右指针开始时,是否与数轴重合,如果重合则说明,当前数列只有一个元素。若不重合,则接着将起始点设为0,终止点设为当前左右指针的值 以及起始点为当前左右指针的值+1,终点设为当前数列的末尾。
[1] 与 [4,3,2]
快速排序的代码实现
def quick_sort(nums, left, right):
temp_right = right
temp_left = left
# 定义终止条件
if left == right:
return
# 定义数轴
axis = left
# 执行主判断
while left < right:
# 判断右指针的数值是否小于数轴
if nums[axis] > nums[right]:
# 如果 数轴的值 > 左指针所指向的值 则移动左指针, 直到发现左指针所指向的值 > 数轴的值
while nums[axis] > nums[left]:
left += 1
# 交换当前左右指针的元素
nums[right], nums[left] = nums[left], nums[right]
# 移动右指针
right -= 1
# 当左右指针相遇时
if left == right:
# 将当前左右指针指向的数字与数轴的数字互换
nums[left], nums[axis] = nums[left], nums[axis]
print(nums)
# 执行操作
quick_sort(nums, temp_left, axis)
quick_sort(nums, axis + 1, temp_right)
return nums
if __name__ == "__main__":
test = [5, 4, 3, 6, 1, 2]
print("answer is", quick_sort(test, 0, len(test) - 1))
运行结果:
[1, 4, 3, 6, 2, 5]
[1, 2, 3, 6, 4, 5]
[1, 2, 3, 6, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
answer is [1, 2, 3, 4, 5, 6]
Process finished with exit code 0
不得不说的,快速排序的思路和代码差别不是很大,思路和代码的关系都写到注释里了
我们再来看看
规则:如果右指针所指向的数字 < 数轴,则向右移动左指针,否则一直向左移动右指针。直到发现左指针所指向的数字 > 数轴,然后交换当前左右指针的元素。重复执行上述直到左指针碰到右指针,将当前左右指针指向的数字与数轴的数字互换
为什么规则会是这样制定呢?
回看快速排序的核心思想,在数组中抽一个数字当数轴,大于数轴的往右放,小于数轴的往左放。规则中:如果右指针所指向的数字 < 数轴,则向右移动左指针,否则一直向左移动右指针映射就是这一点,如果右指针所指向的数字 < 数轴说明,这个数字太小了,不该待在右边,而是左边。那我们要换到左边的哪里呢?规则:左指针所指向的数字 > 数轴找到了一个同样不应该在左边的数字,因为数字大的应该呆在右边。然后规则:当前左右指针指向的数字与数轴的数字互换。则解决了换到哪里的问题。
有人可能会问,万一我左边找不到不符合条件的数字呢(比数轴要大的数字)?那就会发生,左指针与右指针相遇,数轴和左右指针指向的值互换这种情况。那说明什么?左边的数字都符合条件,与其将数字一个个挪到数轴(别忘了,我们是选择当前子数列的首项,数轴的左边没有元素)的左边,还不如将数轴的值移到左边数字的最靠左位置(因为我们判断出左边的数字都小于数轴)。