Python的sort()
之前學習第九章的排序小結的時候,對sort()排序方法不理解,因為括號里面帶了自定義的比較函數。
后來查手冊,才發現sort()里面本來就帶了這樣的參數。能夠自定義比較方法,確實很靈活。
不僅如此,在網上查到一個博客,作者不單停留在這表面,還查究了sort()的排序算法,確實有意思。
全文抄錄如下:
http://blog.donews.com/maverick/archive/2006/07/09/951101.aspx
學習筆記:Python的排序
Python語言內置了sort方法,可以很方便地對某個List進行排序:
L = [6, 5, 1, 3, 4, 2]
L.sort()
print L
---------- Run Python Program ----------
[1, 2, 3, 4, 5, 6]
某些時候,我們希望按照自己定義的排序規則來排序(例如,按關鍵詞的權重排序,按人的年齡排序,等等)。在Java語言中,我們可以自定義Comparator來實現,Python中也提供了類似的辦法。
若List中每個元素都是2-tuple,tuple中第一個元素為String類型的keyword,第二個元素為該字符串對應的權重(int類型),希望按照權重排序(從高到低),則可以這樣:
def my_cmp(E1, E2):
?? ?return -cmp(E1[1], E2[1])?? ?#compare weight of each 2-tuple
?? ??? ??? ??? ??? ?#return the negative result of built-in cmp function
?? ??? ??? ??? ??? ?#thus we get the descend order
L = [('a', 0), ('b', 1), ('c', 2), ('d', 3)]
L.sort(my_cmp)
print L
---------- Run Python Program ----------
[('d', 3), ('c', 2), ('b', 1), ('a', 0)]
正因為可以自定義cmp方法,我們不妨探究一下,built-in的sort方法,到底是采用的哪一種排序算法:
from random import shuffle
def my_cmp(E1, E2):
?? ?print 'E1:', E1, 'E2:', E2
?? ?return cmp(E1, E2)
L = range(0, 10)
shuffle(L)
print L
L.sort(my_cmp)
---------- Run Python Program ----------
[5, 3, 7, 6, 2, 8, 9, 4, 1, 0]
E1: 3 E2: 5
E1: 7 E2: 3
E1: 7 E2: 5
E1: 6 E2: 5
E1: 6 E2: 7
E1: 2 E2: 6
E1: 2 E2: 5
E1: 2 E2: 3
E1: 8 E2: 5
E1: 8 E2: 7
E1: 9 E2: 6
E1: 9 E2: 8
E1: 4 E2: 6
E1: 4 E2: 3
E1: 4 E2: 5
E1: 1 E2: 6
E1: 1 E2: 4
E1: 1 E2: 3
E1: 1 E2: 2
E1: 0 E2: 5
E1: 0 E2: 3
E1: 0 E2: 2
E1: 0 E2: 1
可以看到,每次調用my_cmp,E1依次是List中的第2、3、4……直到最后一個元素,可以肯定sort不是采用的分治法(devide-and-conqure)
看 前三次調用,可以發現sort采用的是典型的插入排序——也就是說,將新元素插入已排序部分的合適位置,查找位置時采用的似乎是從后向前線形探察的辦法。 從元素6開始,新元素不再直接與已排序部分的最后元素比較,而是先與中間值比較,采用二分檢索探察合適位置,這樣,可以把時間代價從n縮小到 log(n)。
至此,我們可以認為,built-in的sort方法,采用的是“二分法插入排序”(binary insertion)的算法。
為了檢測這個結論,可以輸入一個已排序的數組,看看結果。
L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
L.sort(my_cmp)
---------- Run Python Program ----------
E1: 1 E2: 0
E1: 2 E2: 1
E1: 3 E2: 2
E1: 4 E2: 3
E1: 5 E2: 4
E1: 6 E2: 5
E1: 7 E2: 6
E1: 8 E2: 7
E1: 9 E2: 8
E1: 10 E2: 9
結果發現,比較的次數非常少,插入每個元素的時候,只會與它之前緊鄰的元素比較,而不是二分檢索。這真是個有意思的現象。
改一改程序
L = [0, 1, 2, 3, 4, 5, 6, 8, 7, 9, 10]
L.sort(my_cmp)
---------- Run Python Program ----------
E1: 1 E2: 0
E1: 2 E2: 1
E1: 3 E2: 2
E1: 4 E2: 3
E1: 5 E2: 4
E1: 6 E2: 5
E1: 8 E2: 6
E1: 7 E2: 8
E1: 7 E2: 4
E1: 7 E2: 6
E1: 7 E2: 8
E1: 9 E2: 4
E1: 9 E2: 7
E1: 9 E2: 8
E1: 10 E2: 5
E1: 10 E2: 8
E1: 10 E2: 9
可以看到,在數字8以前,List中的元素都是有序的,于是sort算法也只比較欲插入元素和已排序序列的最后一個元素;一旦發現輸入序列不是自然有序之后,就采用二分插入排序算法。
這樣的混合排序算法,相對單純的插入排序,保證了最好條件下時間代價最低,也減小了一般情況下的時間代價。
p.s.
寫完之后查閱Python的文檔,發現sort采用的是混合(hybrid)排序,規模小的時候采用binary insertion,規模大的時候采用samplesort
總結
以上是生活随笔為你收集整理的Python的sort()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 打印不换行
- 下一篇: websocket python爬虫_p