已發布·持續改進
Algorithm
了解陣列、鏈結串列、堆疊、佇列與雜湊表的運作原理及各操作的時間複雜度,學會依情境選擇合適的資料結構。
資料結構是資料在記憶體中的組織方式,以及在這種組織方式上能有效率完成的操作。本主題介紹幾乎所有程式都會用到的五種基礎結構:陣列與動態陣列、鏈結串列、堆疊、佇列與雙端佇列,以及雜湊表。同時也會說明連續記憶體與鏈結記憶體的差異、雜湊函式、碰撞與負載因子。
選擇哪種資料結構,決定了同一個操作是 O(1) 還是 O(n)。用從串列開頭移除元素的方式實作佇列,或在串列中做成員檢查,資料一多程式就會明顯變慢。了解 Python 的 list、deque、dict、set,C++ 的 vector、deque、unordered_map,Java 的 ArrayList、ArrayDeque、HashMap,以及 TypeScript 的 Array、Map、Set 背後究竟是什麼結構,就能事先避開這些陷阱,這也是技術面試最先考的內容。
建議先用小例子手動推演每種結構,看清記憶體中到底移動了什麼。接著親手實作堆疊、環形緩衝區佇列與分離鏈結法雜湊表,把各操作的複雜度整理成表格並用計時器實際量測。最後透過練習題培養為每個問題挑選合適結構的能力。
陣列支援以索引 O(1) 存取且對快取友善;鏈結串列可以在已持有的節點旁以 O(1) 插入與刪除。
動態陣列以固定倍數擴充容量並複製元素,因此偶爾出現的昂貴附加攤銷下來仍是 O(1)。
堆疊取出最新的元素,佇列取出最早的元素。雙端佇列與環形緩衝區能讓兩端的操作都達到 O(1)。
雜湊表把鍵對應到桶中,平均 O(1) 完成查找;以分離鏈結法等方式處理碰撞,負載因子超過上限時進行擴充。
以分離鏈結法實作的雜湊表:用鍵的雜湊值對桶數取餘數來選擇桶,鍵已存在時只替換值,負載因子超過 0.75 時把桶數加倍並重新插入所有鍵值對。程式也示範了把串列當作堆疊、把 deque 當作佇列的用法。
data_structures.py
from collections import deque
class HashMap:
"""Separate chaining: each bucket is a list of (key, value) pairs."""
def __init__(self, capacity=8):
self.buckets = [[] for _ in range(capacity)]
self.size = 0
def _bucket(self, key):
return self.buckets[hash(key) % len(self.buckets)]
def put(self, key, value):
bucket = self._bucket(key)
for i, (k, _) in enumerate(bucket):
if k == key:
bucket[i] = (key, value)
return
bucket.append((key, value))
self.size += 1
if self.size > 0.75 * len(self.buckets): # load factor limit
old = self.buckets
self.buckets = [[] for _ in range(2 * len(old))]
for pairs in old:
for k, v in pairs:
self._bucket(k).append((k, v))
def get(self, key, default=None):
for k, v in self._bucket(key):
if k == key:
return v
return default
stack = [1, 2, 3]
stack.append(4)
print("stack pop:", stack.pop()) # 4 (LIFO)
queue = deque([1, 2, 3])
queue.append(4)
print("queue popleft:", queue.popleft()) # 1 (FIFO)
ages = HashMap()
for name, age in [("ada", 36), ("alan", 41), ("grace", 85)]:
ages.put(name, age)
ages.put("ada", 37)
print("ada:", ages.get("ada"), "size:", ages.size) # ada: 37 size: 3
python data_structures.py共六章,帶你從安裝一步步認識 基礎資料結構 的核心概念。
在這裡提問、分享經驗,交流關於 基礎資料結構 的看法。
還沒有討論。來發起第一則吧。
0 則留言
登入 · 登入後即可留言。
來留下第一則留言吧。