1. 程式人生 > >高階Python----常用的資料結構與演算法

高階Python----常用的資料結構與演算法

前言


高階Python系列文章是筆者想要突破自己目前的技術生涯瓶頸而作,不具有普適性。本文主要是介紹Python在資料結構和演算法中常用的函式。這也是資料分析領域必備知識點。

也不是特地為了某些讀者而作,想著提高自己的同時,能方便他人就更好了。懂分享的人,一定會快樂!

常用的四個模組應該是:collections,heapq,operator,itertools。其中,collections是日常工作中的重點/高頻模組。

另外,正確學習這些技巧的姿勢應該是:開啟電腦,實現數遍,嘗試不同解決辦法和程式設計方式。

注:所有程式碼在Python3.5.1中測試。


collections模組


  • deque
from collections import deque

"""學習固定長度的deque"""
q = deque(maxlen=5)    # 建立一個固定長度的佇列,當有新記錄加入已滿的佇列時,會自動移除最老的記錄。

q.append(1)    # 新增元素


"""學習不固定長度的deque,從佇列兩端新增或彈出元素的複雜度為o(1)."""
q = deque()    # 建立一個無界限的佇列,可以在佇列兩端執行新增和彈出操作

q.append(1)    # 新增元素

q.appendleft(2
) # 向左邊新增一個元素 q.pop() # 彈出佇列尾部的記錄 q.popleft() # 彈出佇列頭部的記錄
  • defaultdict
    用於建立有多個value對應一個key的字典。比如建立value可重複(list儲存)的該字典:dic = {“a”: [1, 2 , 2, 3, 3], “b”: [1, 2]}。或建立value不可重複(set儲存)的該字典:dic = {“a”: { 1, 2, 3}, “b”: {1, 2} }
from collections import defaultdict

d_list = defaultdict(list)    # list
d['a'].append(1) d['a'].append(2) d['a'].append(2) d['a'].append(3) d['a'].append(3) d_set = defaultdict(set) # set d['a'].add(1) d['a'].add(2) d['a'].add(3)
  • OrderedDict
    OrderedDict內部維護了一個雙向連結串列,會根據元素加入的順序來排列鍵的位置。一個新加入的元素被放在連結串列的末尾,然後,對已存在的鍵做重新賦值但不會改變鍵的順序。作用:嚴格控制元素初始新增的順序。
from collections import OrderedDict

d = OrderedDict()    # 例項化
d['a'] = 1
d['b'] = 2
  • Counter
    作用:統計可雜湊的序列中元素出現的次數。(可雜湊:一種特性,具備該特性的物件在其生命週期內必須不可變。在Python中,有整數、浮點數、字串、元組。)
from collections import Counter

test = ['a', 'a', 'b', 'c', 'b', 'd', 'a', 'c', 'e', 'f', 'd']    # 測試集

word_count = Counter(test)    # 呼叫,傳參

print(word_count)    # 輸出:Counter({'a': 3, 'b': 2, 'c': 2, 'd': 2, 'f': 1, 'e': 1})

word_count.most_common(3)    # 獲取出現頻次前3的單詞

word_count['a']    # 獲取某個單詞的頻次

Counter還可以將兩個資料集進行數學運算。如下:

from collections import Counter

test = ['a', 'a', 'b', 'c', 'b', 'd', 'a', 'c', 'e', 'f', 'd']    # 測試集

test1 = ['a', 'b', 'c', 'd', 'e', 'f']    # 另一測試集

a = Counter(test)    # 統計test
b = Counter(test1)    # 統計test1

print(a)    # 輸出:Counter({'a': 3, 'b': 2, 'c': 2, 'd': 2, 'f': 1, 'e': 1})
print(b)    # 輸出:Counter({'b': 1, 'a': 1, 'f': 1, 'c': 1, 'd': 1, 'e': 1})

c = a + b    # 統計兩個資料集
print(c)    # 輸出:Counter({'a': 4, 'b': 3, 'c': 3, 'd': 3, 'f': 2, 'e': 2})

c = a - b    # Counter({'a': 2, 'b': 1, 'c': 1, 'd': 1})
c = b - a    # Counter()


heapq模組


heapq 模組提供了堆演算法。heapq是一種子節點和父節點排序的樹形資料結構。這個模組提供heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2]。為了比較不存在的元素被人為是無限大的。堆最重要的特性就是heap[0]總是最小的那個元素。

  • nlargest/nsmallest
import heapq

"""簡單的資料集"""
numbers = [11,22,33,-9,0,5,-11]    # 測試資料集

heapq.nlargest(3,numbers)    # 獲得前3最大的元素

heapq.nsmallest(3,numbers)    # 獲得前3最小的元素

"""複雜的資料集"""
people_info = [
    {'name': "guzhenping", 'age':19, 'score':90},
    {'name': "xiao gu", 'age':21, 'score':100}
]

max_age = heapq.nlargest(1,people_info, key=lambda people_info: people_info['age'])    # 獲取最大年齡的個人

min_score = heapq.nsmallest(1, people_info, key=lambda info: info['score'])    # 獲取最低分數的個人 
  • heapify
    作用:對元素進行堆排序。保證最小的元素在為第一個元素。
import heapq
nums = [11, 22, 33, 44, 0, -1,20,-12]     # 測試資料集

heapq.heapify(nums)    # 轉化成堆排序的列表

print(nums)    # 輸出:[-12, 0, -1, 22, 11, 33, 20, 44]。

heapq.heappop(nums)    # 彈出最小的元素,同時讓第二小的元素變成第一小
  • heappop/heappush
    heappop和heappush是在堆排序中常用的方法。heapq.heappop()作用:將第一個元素(最小的)彈出,然後將第二小的元素放在第一個。heapq.heappush()是插入操作。兩者複雜度o(logN),N代表堆中元素的數量。

以一個優先順序佇列進行舉例:

import heapq

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        heapq.heappush(self._queue, (priority, self._index, item))
        self._index += 1

    def pop(self):
        data = heapq.heappop(self._queue)
        print(data)
        return data[-1]

if __name__ == '__main__':
    q = PriorityQueue()

    q.push("guzhenping", 1)
    q.push("xiao gu", 3)
    q.push("xiao ping",1)

    # 列印測試
    while len(q._queue) != 0:
        print(q.pop())


結語


隨便整理一下,發現內容已經很多了。如果你沒有見過上述的常用函式,可以好好學習一下。

這裡還有很多沒說的內容:

  • operator.itemgetter()和operator.attrgetter()的使用,以及同lambda函式的區別。
  • collections中的namedtuple()、ChainMap()的使用
  • ……

希望以後能再繼續。

2年Python開發經驗,但是,還有很多原理不懂。以前的不求甚解,變成了現在的知識瓶頸。所以,來啊,快活啊,一起進階Python啊!

有興趣和我一起提高Python技術的同學,歡迎加入微信群–高階Python打卡群。掃碼進入:

這裡寫圖片描述

也歡迎關注我的微信公眾平臺號:
這裡寫圖片描述