Item 46: Use Built-in Algorithms and Data Structures

 使用內置數據結構和算法        python

        當你實現很是小的的Python程序時,你可能會看到由你的代碼的算法複雜性而形成的減速。 這個一般不是Python語言自己速度的形成,這更有多是由於沒有爲您的問題使用最好的算法和數據結構。幸運的是Python標準庫有許多內置的算法和數據結構能夠使用。除了速度,使用這些經常使用的算法和數據結構可讓你的生活更輕鬆。 你可能想使用的一些更有力的工具,這是一個棘手的問題。 避免從新實現經常使用功能將會節省您的時間。算法

        Double-ended Queue(雙端隊列)
        deque類是在collections模塊中,它是一個double-ended隊列。從deque隊列開始或者結尾,插入或者刪除會花費相同的時間。這個使其成爲先進先出(FIFO)隊列的理想選擇。數據結構

fifo = deque()
fifo.append(1) # Producer
x = fifo.popleft() # Consumer

內置List也能夠實現有序隊列,如fifo。但內置List從列表頭部的插入或刪除項,花費時間是線性的,這比常數慢得多。app

        Ordered Dictionary(有序字典)
        標準字典是無序的。 這意味着具備相同的鍵和值的dict能夠有不一樣的迭代次序。 這種行爲有一個使人驚訝的副產品就是實現字典的快速哈希表。dom

a = {}
a['foo'] = 1
a['bar'] = 2
# Randomly populate ‘b’ to cause hash conflicts
while True:
z = randint(99, 1013)
b = {}
for i in range(z):
b[i] = i
b['foo'] = 1
b['bar'] = 2
for i in range(z):
del b[i]
if str(b) != str(a):
break
print(a)
print(b)
print('Equal?', a == b)
>>>
{'foo': 1, 'bar': 2}
{'bar': 2, 'foo': 1}
Equal? True

        collections模塊中的OrderedDict類是一種特殊類型的字典,它跟蹤其鍵的插入順序。 迭代鍵OrderedDict具備可預測的行爲。 這能夠大大簡化測試和調試經過使全部代碼肯定性。數據結構和算法

a = OrderedDict()
a['foo'] = 1
a['bar'] = 2
b = OrderedDict()
b['foo'] = 'red'
b['bar'] = 'blue'
for value1, value2 in zip(a.values(), b.values()):
print(value1, value2)
>>>
1 red
2 blue

        Default Dictionary
        字典對記帳和跟蹤統計很是有用。內建的字典類型是不能假設任何鍵已經存在。 這使得它作一些簡單的事情時顯得笨拙,如增長一個存儲在字典中的計數器。函數

stats = {}
key = 'my_counter'
if key not in stats:
    stats[key] = 0
stats[key] += 1

collections模塊中的defaultdict類簡化了當key不存在時自動存儲默認值。 全部你須要作的是提供每次鍵丟失時將返回默認值的函數。 在這裏例如,int內置函數返回0如今,遞增計數器是
簡單。int()->0工具

stats = defaultdict(int)
stats['my_counter'] += 1

        Heap Queue
   關於這裏,heap這種數據結構的介紹有一個簡單的blog能夠去看一下http://blog.csdn.net/minxihou/article/details/51857518
堆是用於維護優先級隊列的有用數據結構。 heapq模塊提供了在標準list類型中建立堆的功能使用函數heappush,heappop和nsmallest等函數。任何優先級的項能夠按任何順序插入堆中。測試

a = []
heappush(a, 5)
heappush(a, 3)
heappush(a, 7)
heappush(a, 4)

老是先移除最高優先級(lowest number)的項..net

print(heappop(a), heappop(a), heappop(a), heappop(a))
>>>
3 4 5 7

生成的list在heapq以外很容易使用。 訪問堆的0索引將老是返回最小的項。

a = []
heappush(a, 5)
heappush(a, 3)
heappush(a, 7)
heappush(a, 4)
assert a[0] == nsmallest(1, a)[0] == 3

list的sort方法保持不變。

print('Before:', a)
a.sort()
print('After:' , a)
>>>
Before: [3, 4, 7, 5]
After: [3, 4, 5, 7]

        Bisection

        調用index方法查找列表中的項須要花費與list長度成線性比例的時間。

x = list(range(10**6))
i = x.index(991234)

使用bisect模塊的方法,如:bisect_left,是使用二分查找的方法。它返回的索引是插入點值插入序列。

i = bisect_left(x, 991234)

二分搜索的複雜度是對數的。 這意味着使用bisect搜索100萬個項的list的速度是使用線性索引方式搜索的14倍。It’s way faster!

        Iterator Tools
        tertools內置模塊包含大量有用與迭代器相關的函數。不是全部這些都在Python 2中可用,但它們能夠輕鬆地使用經過查看模塊中記錄的simple recipes。 請參閱help(itertools)得到更多詳細信息。
itertools中的函數主要分爲三類:
    Linking iterators together
        •chain:將多個迭代器組合成一個順序迭代器。
        •cycle:一直重複迭代器的項。
        •tee:將單個迭代器拆分爲多個並行迭代器。
        •zip_longest:內置zip函數的變體,當迭代的幾個對象長度不一樣的時候有更好的表現。
    Filtering items from an iterator
        •islice:經過數字索引切片迭代器,而不進行復制。
        •takewhile:當斷言函數返回Ture時返回迭代器中的項。
        •dropwhile:當斷言函數第一次爲False時,返回迭代器中的項。
        •filterfalse:當斷言函數第一次爲False時,返回迭代器中全部的項。 與內置函數filter做用相反。
    Combinations of items from iterators(組合迭代器中的項)
        •product:返回迭代器中項的笛卡爾乘積,是一種很好的替代深層嵌套列表推導的方法。
        •permutations:返回長度爲N的有序排列迭代器。
        •combination:返回長度爲N的,用迭代器中未重複項所組成的無序組合。
在itertools模塊中有更多的功能和recipes可用不能在這裏一一說起。 每當你發現本身處理一些棘手的迭代代碼,itertools文檔是值得再次查看,看看是否有你想要的東西。

        Things to Remember
        一、使用Python的內置模塊用於算法和數據結構。   

        二、不要本身從新實現此功能。

相關文章
相關標籤/搜索