■  快速排序

  个人感觉快速排序相对还好理解一些。大的框架上来说,快速排序使用的是递归的思想。

  具体描述: 首先获取数组的第0元素作为一个基准(pivot),然后从第1元素开始向右遍历,将所有小于基准的值都尽量往左摆放。具体来说那就是在遍历过程中建立两个游标,一个游标i用来做全遍历,另一个游标d_index用来标明到那个元素为止,前面的所有元素都已经是被判定为小于基准因此被放到左边的边界。比较第i元素和基准大小,对于每比较到一次第i元素小于基准的情况,就交换当前i和d_index两个元素,并且将d_index自增1。遍历完一趟后此时应该交换d_index-1(此时的第d_index元素是属于大于基准的哦),这样基准元素就到了它正确的位置,剩余的事情就是再快速排序一下整个序列中[0:d_index-1]以及[d_index:]这两个子序列即可。

  另外由于用了递归,所以得斟酌下递归返回的条件。可以想象,当递归不断深入,对于右半区的序列而言返回的d_index是越来越大的,总有一天+1后会大于right,同时左半区越来越小,会在某一天等于0。这两者都是跳出递归的条件。总的来说,可以设置一个left<right的条件,控制跳出。

  用代码来说:

def quick_sort(lst,left=0,right=None):
    if right is None:
        right = len(lst) - 1
    if left < right:
        partitionIndex = partition(lst,left,right)
        # 递归处理左半区和右半区(虽说是半区,但并不一定是对半开,根据partitionIndex大小不同可能会有偏颇
        quick_sort(lst,left,partitionIndex-1)
        quick_sort(lst,partitionIndex+1,right)

def partition(lst,left,right):
    '''
    对lst的[left:right+1]序列进行分区,最终返回分区元素的下标d_index-1
    函数返回时数组所处的状态应该是d_index-1左边的都比它小,右边都比它大
    :param lst:
    :param left:
    :param right:
    :return:
    '''
    pivot = left
    i = d_index = pivot + 1
    while i <= right:
        if lst[i] < lst[pivot]:
            lst[d_index],lst[i] = lst[i],lst[d_index]
            d_index += 1
        i += 1
    lst[d_index-1],lst[pivot] = lst[pivot],lst[d_index-1]
    return d_index - 1

 

  (上面的"将小于基准的元素尽量放到左边"的逻辑是从左到右依次循环遍历,碰到小于基准的放到当前未遍历区的最左端。另外还可能有多种实现逻辑,比如两个游标分别从左右开始,右边游标遇到小于基准的值就将其值赋到左边,左边游标则是遇到大雨基准值的放到右边。需要注意要灵活一些。)

  如果要求quick_sort只能接受一个lst参数,那么可以考虑将递归放在partition中进行:

def partition(lst,left,right):
    if left >= right:
        return
    pivot = left
    d = i = left + 1
    while i <= right:
        if lst[pivot] < lst[i]:
            lst[d],lst[i] = lst[i],lst[d]
            d += 1
        i += 1
    lst[d-1],lst[pivot] = lst[pivot],lst[d-1]
    pivot = d - 1    # 别忘了这步,否则pivot是0
    partition(lst,left,pivot-1)
    partition(lst,pivot+1,right)

def quick_sort(lst):
    left = 0
    right = len(lst) - 1
    partition(lst,left,right)
View Code

相关文章:

  • 2021-10-22
  • 2022-12-23
  • 2021-12-05
  • 2021-12-28
  • 2022-12-23
  • 2021-05-03
  • 2020-02-22
  • 2021-11-15
猜你喜欢
  • 2022-01-13
  • 2021-10-25
  • 2022-01-17
  • 2021-12-15
  • 2020-11-16
  • 2021-09-27
相关资源
相似解决方案