算法基础:快排
什么是快排?
排序思路
排序代码
快速排序代码——第一步
def quick_sort_x(data, left, right): if left < right: mid = partition(data, left, right) quick_sort_x(data, left, mid - 1) quick_sort_x(data, mid + 1, right)
怎么写partition函数
快速排序代码——第二步
def partition(data, left, right): tmp = data[left] while left < right: while left < right and data[right] >= tmp: right -= 1 data[left] = data[right] while left < right and data[left] <= tmp: left += 1 data[right] = data[left] data[left] = tmp return left
还不理解partition函数?
效率性能
快排和冒泡算法性能比较
import random import time import copy def cal_time(func): def wrapper(*args, **kwargs): t1 = time.time() result = func(*args, **kwargs) t2 = time.time() print("%s running time: %s secs." % (func.__name__, t2 - t1)) return result return wrapper @cal_time def bubble_sort_1(li): for i in range(len(li) - 1): exchange = False for j in range(len(li) - i - 1): if li[j] > li[j+1]: li[j], li[j+1] = li[j+1], li[j] exchange = True if not exchange: break def quick_sort_x(data, left, right): if left < right: mid = partition(data, left, right) quick_sort_x(data, left, mid - 1) quick_sort_x(data, mid + 1, right) def partition(data, left, right): tmp = data[left] while left < right: while left < right and data[right] >= tmp: right -= 1 data[left] = data[right] while left < right and data[left] <= tmp: left += 1 data[right] = data[left] data[left] = tmp return left @cal_time def quick_sort(data): return quick_sort_x(data, 0, len(data) - 1) data = list(range(10000)) random.shuffle(data) data1 = copy.deepcopy(data) data2 = copy.deepcopy(data) bubble_sort(data1) quick_sort(data2)
下面分别是10000和100000列表的时间
data = list(range(10000)) bubble_sort running time: 10.56360411643982 secs. quick_sort running time: 0.03200173377990723 secs. data = list(range(100000)) bubble_sort running time: 1173.2021033763885 secs. quick_sort running time: 0.4220242500305176 secs.
结论:元素越多,性能差距越明显
1、因为冒泡每一趟只完成一个元素的归位
2、而快排每一趟不至一个元素的归位,相同的时间归位的元素越多说明效率就越高
3、从复杂度方面讲:
冒泡是:n*n 64*64
快排是:O(logn) 64*6
快排、冒泡、系统自带排序性能比较
import random import time import copy import sys def cal_time(func): def wrapper(*args, **kwargs): t1 = time.time() result = func(*args, **kwargs) t2 = time.time() print("%s running time: %s secs." % (func.__name__, t2 - t1)) return result return wrapper @cal_time def bubble_sort(li): for i in range(len(li) - 1): exchange = False for j in range(len(li) - i - 1): if li[j] > li[j + 1]: li[j], li[j + 1] = li[j + 1], li[j] exchange = True if not exchange: break def quick_sort_x(data, left, right): if left < right: mid = partition(data, left, right) quick_sort_x(data, left, mid - 1) quick_sort_x(data, mid + 1, right) def partition(data, left, right): tmp = data[left] while left < right: while left < right and data[right] >= tmp: right -= 1 data[left] = data[right] while left < right and data[left] <= tmp: left += 1 data[right] = data[left] data[left] = tmp return left @cal_time def quick_sort(data): return quick_sort_x(data, 0, len(data) - 1) @cal_time def sys_sort(data): return data.sort() data = list(range(1000000)) random.shuffle(data) data1 = copy.deepcopy(data) data2 = copy.deepcopy(data) data3 = copy.deepcopy(data) quick_sort(data2) sys_sort(data3) bubble_sort(data1)
测试结果:
quick_sort running time: 5.9070000648498535 secs. sys_sort running time: 0.559999942779541 secs.
结论:最快的是系统自带排序,下来是快排,最后是冒泡,系统自带排序为什么会最快了?
def sort(self, key=None, reverse=False): # real signature unknown; restored from __doc__ """ L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE* """ pass
系统自带排序为什么会最快了?
上面是系统的类,就一个pass,因为自带的是用C写的.绝大多数的语言,默认的都是快排,但是python不是是用C语言写的
不改装逼的时候不要装逼,自己写的时候,就调用系统自带的快排。
哪我们为什么要学算法哪?
算法是能力的一个体现,就比如你数学学的好,说明你思维能力好
问题
[9999, 9998, 9997, 9996, 9995, 9994, 9993, 9992, 9991, 9990, 9989, 9988,...0] 就像这样全部是倒序
import random import time import copy import sys def cal_time(func): def wrapper(*args, **kwargs): t1 = time.time() result = func(*args, **kwargs) t2 = time.time() print("%s running time: %s secs." % (func.__name__, t2 - t1)) return result return wrapper @cal_time def bubble_sort_1(li): for i in range(len(li) - 1): exchange = False for j in range(len(li) - i - 1): if li[j] > li[j+1]: li[j], li[j+1] = li[j+1], li[j] exchange = True if not exchange: break def quick_sort_x(data, left, right): if left < right: mid = partition(data, left, right) quick_sort_x(data, left, mid - 1) quick_sort_x(data, mid + 1, right) def partition(data, left, right): tmp = data[left] while left < right: while left < right and data[right] >= tmp: right -= 1 data[left] = data[right] while left < right and data[left] <= tmp: left += 1 data[right] = data[left] data[left] = tmp return left @cal_time def quick_sort(data): return quick_sort_x(data, 0, len(data) - 1) @cal_time def sys_sort(data): return data.sort() sys.setrecursionlimit(100000) a = range(10000) data = list(reversed(a)) data1 = copy.deepcopy(data) data2 = copy.deepcopy(data) data3 = copy.deepcopy(data) bubble_sort(data1) quick_sort(data2) sys_sort(data3)
测试结果如下:
bubble_sort running time: 0.20701169967651367 secs. quick_sort running time: 0.1020057201385498 secs. sys_sort running time: 0.0 secs.
关于递归一定要添加:sys.setrecursionlimit(100000),因为Python中递归的最大次数的限制不加报如下错误:
当在我自己的机器运行以上代码时,发现最多能打印到998,然后就会抛出 “RuntimeError: maximum recursion depth exceeded” 的错误了。 嘿,还真有限制。但转念一想,python不会这么弱吧。经过一番查找,发现这是python专门设置的一种机制用来防止无限递归造成Python溢出崩溃, 最大递归次数是可以重新调整的。 (http://docs.python.org/2/library/sys.html#sys.setrecursionlimit),修改代码如下:
sys.setrecursionlimit(100000) a = range(10000) data = list(reversed(a)) #data.sort() #random.shuffle(data) data1 = copy.deepcopy(data) data2 = copy.deepcopy(data) data3 = copy.deepcopy(data) bubble_sort(data1) quick_sort(data2)
还需要注意如果:data = list(range(1000, 1, -1)) 中的1000设置成10000就会报如下错误:
总结
1、快排最好情况下:【0,1,2,3,4,5,6,...,9999】
sys.setrecursionlimit(100000) data = list(range(1000)) data1 = copy.deepcopy(data) data2 = copy.deepcopy(data) data3 = copy.deepcopy(data) bubble_sort_1(data1) quick_sort(data2) sys_sort(data3)
测试结果如下:
bubble_sort_1 running time: 0.0 secs. quick_sort running time: 0.07200407981872559 secs. sys_sort running time: 0.0 secs.
2、正常情况下:[15, 781, 698, 460, 445, 522, 470, 225, 925, 840, 334, 664, 434...2]
sys.setrecursionlimit(100000) data = list(range(1000)) random.shuffle(data) data1 = copy.deepcopy(data) data2 = copy.deepcopy(data) data3 = copy.deepcopy(data) bubble_sort_1(data1) quick_sort(data2) sys_sort(data3)
测试结果如下:
bubble_sort_1 running time: 0.14500832557678223 secs. quick_sort running time: 0.002000093460083008 secs. sys_sort running time: 0.0009999275207519531 secs.
3、最坏情况下:[999, 998, 997, 996, 995, 994, 993, 992,...0]
sys.setrecursionlimit(100000) a = range(1000) data = list(reversed(a)) data1 = copy.deepcopy(data) data2 = copy.deepcopy(data) data3 = copy.deepcopy(data) bubble_sort(data1) quick_sort(data2) sys_sort(data3)
测试结果如下:
bubble_sort_1 running time: 0.2170124053955078 secs. quick_sort running time: 0.08100461959838867 secs. sys_sort running time: 0.0 secs.
下图为冒泡、快排和系统自带的对比表
作者:罗阿红
出处:http://www.cnblogs.com/luoahong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。