《算法图解》笔记(3) 快速排序

基线条件(base case)和递归条件(recursive case)

递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环。

分而治之(divide and conquer,D&C)

问题:假设你是农场主,有一小块土地。大小为640m × 1680m。你要将这块地均匀地分成方块,且分出的方块要尽可能大。如何将一块地均匀地分成方块,并确保分出的方块是最大的呢?

使用D&C策略!D&C算法是递归的。使用D&C解决问题的过程包括两个步骤。

  1. 找出基线条件,这种条件必须尽可能简单。(涉及数组的递归函数时,基线条件通常是数组为空或只包含一个元素。)
  2. 不断将问题分解(或者说缩小规模),直到符合基线条件。

快速排序

快速排序的工作原理。首先,从数组中选择一个元素,这个元素被称为基准值(pivot)。

接下来,找出比基准值小的元素以及比基准值大的元素。这被称为分区(partitioning)。

最后对这两个子数组进行快速排序,再合并结果,就能得到一个有序数组!

快速排序代码:

def quicksort(array):
    if len(array) < 2:
        return array
    else:        
        pivot = array[0]
        less =[]
        '''  
        for i in array[1:]:
            if i <= pivot:
                less.append(i)   #列表存入元素用append
        return less
        '''
        #这里用了python的列表解析,后面小贴士会介绍
        less = [i for i in array[1:] if i<=pivot]        
        greater = [i for i in array[1:] if i>pivot]      
        return  quicksort(less) + [pivot] + quicksort(greater)

print(quicksort([10,5,2,3]))
print(quicksort([10,5,2,3,11,15,12]))

小结

  •  D&C将问题逐步分解。使用D&C处理列表时,基线条件很可能是空数组或只包含一个元素的数组
  • 实现快速排序时,请随机地选择用作基准值的元素。快速排序的平均运行时间为O(n log n)。
  • 大O表示法中的常量有时候事关重大,这就是快速排序比合并排序快的原因所在。
  • 比较简单查找和二分查找时,常量几乎无关紧要,因为列表很长时,O(log n)的速度比O(n)快得多

小贴士

列表解析(List Comprehensions)根据已有列表,高效创建新列表的方式。列表解析是Python迭代机制的一种应用,它常用于实现创建新的列表,因此用在[ ]中。

语法:

  • [expression for iter_val in iterable]
  • [expression for iter_val in iterable if cond_expr]

例子:1.x = [i for i in list],将一个 list 映射为另一个 list,每个元素设为变量i

   2.列出1~10中大于等于4的数字的平方

普通方法:

L = []
or i in range(1,11):
    if i >= 4:
         L.append(i**2)
print(L)

输出:[16, 25, 36, 49, 64, 81, 100]

列表解析:

L = [ i**2 for i in range(1,11) if i >= 4 ]
print(L)

输出:[16, 25, 36, 49, 64, 81, 100]

 

posted @ 2019-03-05 21:12  WMXNLFD  阅读(430)  评论(0编辑  收藏  举报