快速排序 -- 从想法到代码的实现

什么是快速排序

听说这是大部分程序员最常用的排序算法,程序员做事就是有效率高,质量好而且快。(好像所有职业要求都是这样的)。快速排序主要是依靠一个数轴,如果大于数轴的就往左放,小于数轴就往右放。

快速排序的思路

核心思想:在数列中选取一个数轴,大于数轴往右放,小于往左放
用[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

不得不说的,快速排序的思路和代码差别不是很大,思路和代码的关系都写到注释里了

我们再来看看
规则:如果右指针所指向的数字 < 数轴,则向右移动左指针,否则一直向左移动右指针。直到发现左指针所指向的数字 > 数轴,然后交换当前左右指针的元素。重复执行上述直到左指针碰到右指针,将当前左右指针指向的数字与数轴的数字互换

为什么规则会是这样制定呢?
回看快速排序的核心思想,在数组中抽一个数字当数轴,大于数轴的往右放,小于数轴的往左放。规则中:如果右指针所指向的数字 < 数轴,则向右移动左指针,否则一直向左移动右指针映射就是这一点,如果右指针所指向的数字 < 数轴说明,这个数字太小了,不该待在右边,而是左边。那我们要换到左边的哪里呢?规则:左指针所指向的数字 > 数轴找到了一个同样不应该在左边的数字,因为数字大的应该呆在右边。然后规则:当前左右指针指向的数字与数轴的数字互换。则解决了换到哪里的问题。
有人可能会问,万一我左边找不到不符合条件的数字呢(比数轴要大的数字)?那就会发生,左指针与右指针相遇,数轴和左右指针指向的值互换这种情况。那说明什么?左边的数字都符合条件,与其将数字一个个挪到数轴(别忘了,我们是选择当前子数列的首项,数轴的左边没有元素)的左边,还不如将数轴的值移到左边数字的最靠左位置(因为我们判断出左边的数字都小于数轴)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值