D&C递归算法-快速排序
①解决问题的过程包括两个步骤:
找出基线条件
不断将问题分解,直到符合基线条件
②使用循环求数字列表的和
def sum(list):
total=0
for x in list:
total+=x
return total
print(sum([2,4,6,8]))
使用递归求数字列表的和
def sum(list):
if list==[]:
return 0
return list[0]+sum(list[1:])
print(sum([1,2,3,4]))
③使用循环求列表中元素的个数
def count(arr):
index=0
for x in arr:
index=index+1
return index
print(count([1,2,3,4]))
使用递归求列表中元素的个数
def count(list):
if list==[]:
return 0
return 1+count(list[1:])
print(count([1,2,3,4]))
④用循环找出列表中最大的数字
def max(arr):
maxnum=arr[0]
for i in range(1,len(arr)):
if arr[i]>maxnum:
maxnum=arr[i]
return maxnum
print(max([1,2,3,4]))
用递归求列表中最大数字
def max(list):
if len(list) == 2:
return list[0] if list[0] > list[1] else list[1]
sub_max = max(list[1:])
return list[0] if list[0] > sub_max else sub_max
print(max([1,2,3,4]))
⑤二分查找的基线条件是数组只包含一个元素,如果要查找的值跟这个元素相同,就找到了,否则,说明不在数组中。
在二分查找的递归条件中,把数组分成两半,其中一半丢掉,对另一半进行二分查找。
快速排序
①最简单的数组的基线条件为数组为空或只包含一个元素,只需原样返回数组,不用排序。
def quicksort(dist)
if len(dist)<2:
return list
②更长的数组,暂时将第一个元素用作基准值,接下来找比基准值小的元素以及比基准值大的元素。
分区
①一个由所有小于基准值的数字组成的子数组
②基准值
③一个由所有大于基准值的数组组成的子数组
如何对子数组进行排序
①对于只包含两个元素的数组(左边的子数组)以及空数组(右边的子数组),进行快速排序
quicksort([15,10])+[33]+quicksort([])#=>[10,15,33]
不管哪个元素作为基准值,这都管用。
②对包含多个元素的数组进行快速排序
1、选择基准值
2、将数组分成两个子数组,小于基准值的元素和大于基准值的元素
3、对这两个子数组进行快速排序
快速排序代码
def quicksort(array):
if len(array)<2:
return array
else:
pivot=array[0]
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]))
再谈大O表示法
①快速排序的运行时间O(n log n)
比较合并排序和快速排序
假设有下面打印列表中每个元素的简单函数
def print_items(list):
for item in list:
print(item)
这个函数遍历列表中每个元素并打印出来,迭代整个列表一次,运行时间为O(n)。现在修改,使打印每个元素前休眠1s.
list=[2,4,6,8,10]
##print_items(list)
from time import sleep
def print_items2(list):
for item in list:
sleep(1)
print(item)
print_items2(list)
运行时间也为O(n)
①有的时候,常量的影响可能很大,对快速查找和合并查找就是如此。快速查找的常量比合并查找小,因此运行时间都为O(n log n),快速查找更快。
平均情况和最糟情况的时间
①最佳情况也就是平均情况O(n)*O(logn) 后者为层数,也即调用栈的高单独,前者为每层需要时间,整个时间为O(n log n)
②最糟情况 O(n2)
小结
①使用D&C处理列表,基线条件很可能是空数组或只包含一个元素的数组。
②实现快速排序时,请随机得选择用作基准值的元素。
③大O表示法中常量有时候事关重大,这就是快速排序比合并排序块的原因所在。
④比较简单查找和二分查找时,常量几乎无关紧要,因为列表很长,O(log n)的速度比O(n)快的多。