[英]Python quicksort - List comprehension vs Recursion (partition routine)
我看了三個美麗的Quicksorts談話,並且正在忙着趕快行動。 我在python中的實現與c非常相似(選擇pivot,圍繞它進行分區並在越來越大的分區上遞歸)。 我認為這不是pythonic 。
所以這是在python中使用list comprehension的實現。
def qsort(list):
if list == []:
return []
pivot = list[0]
l = qsort([x for x in list[1:] if x < pivot])
u = qsort([x for x in list[1:] if x >= pivot])
return l + [pivot] + u
讓我們調用遞歸方法qoortR。 現在我注意到qsortR比大型(r)列表的qsort運行慢得多。 實際上“cmp中超出了最大遞歸深度”,即使對於遞歸方法也是1000個elems。 我在sys.setrecursionlimit中重置。
一些數字:
list-compr 1000 elems 0.491770029068
recursion 1000 elems 2.24620914459
list-compr 2000 elems 0.992327928543
recursion 2000 elems 7.72630095482
所有代碼都在這里 。
我有一些問題:
為什么列表理解這么快?
因為名單理解暗示的C循環比使用Python的慢一般方法快得多for
塊。
對python中遞歸限制的一些啟示。 我首先將它設置為100000,在什么情況下我應該小心?
如果你的內存不足。
試圖對我的筆記本電腦的1000000個元素進行排序(使用遞歸方法)。 如果我想要排序這么多元素,我該怎么辦? 什么樣的優化是可能的?
Python的遞歸會產生這樣的開銷,因為每次調用都會在每次調用時分配大量的堆棧內存空間。
通常,迭代是答案(在統計上99%的用例中將提供更好的性能)。
談論內存結構,如果你有簡單的數據結構,比如字符,整數,浮點數:使用內置的array.array
,它比list
具有更高的內存效率。
您是否嘗試過編寫非遞歸的partition
實現? 我懷疑性能差異純粹是partition
實現。 您正在為實現中的每個元素進行遞歸。
更新
這是一個快速實現。 它仍然不是超快速甚至是高效的,但它比原來的遞歸更好。
>>> def partition(data):
... pivot = data[0]
... less, equal, greater = [], [], []
... for elm in data:
... if elm < pivot:
... less.append(elm)
... elif elm > pivot:
... greater.append(elm)
... else:
... equal.append(elm)
... return less, equal, greater
...
>>> def qsort2(data):
... if data:
... less, equal, greater = partition(data)
... return qsort2(less) + equal + qsort2(greater)
... return data
...
我還認為“傳統”版本中生成的臨時列表數量較多。
當內存變得非常大時,嘗試將列表理解與就地算法進行比較。 下面的代碼在排序100K整數時會得到一個接近執行的時間,但在排序1M整數時,你可能會陷入列表推導解決方案。 我使用4Gb機器進行了測試。 完整代碼: http : //snipt.org/Aaaje2
class QSort:
def __init__(self, lst):
self.lst = lst
def sorted(self):
self.qsort_swap(0, len(self.lst))
return self.lst
def qsort_swap(self, begin, end):
if (end - begin) > 1:
pivot = self.lst[begin]
l = begin + 1
r = end
while l < r:
if self.lst[l] <= pivot:
l += 1
else:
r -= 1
self.lst[l], self.lst[r] = self.lst[r], self.lst[l]
l -= 1
self.lst[begin], self.lst[l] = self.lst[l], self.lst[begin]
# print begin, end, self.lst
self.qsort_swap(begin, l)
self.qsort_swap(r, end)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.