This commit is contained in:
krahets
2025-09-20 20:08:06 +08:00
parent ae2e2535f4
commit 1fca6ca899
9 changed files with 30 additions and 10 deletions
@@ -51,3 +51,9 @@ comments: true
假設取 $n = 8$ ,你可能會發現每條曲線的值與函式對應不上。這是因為每條曲線都包含一個常數項,用於將取值範圍壓縮到一個視覺舒適的範圍內。
在實際中,因為我們通常不知道每個方法的“常數項”複雜度是多少,所以一般無法僅憑複雜度來選擇 $n = 8$ 之下的最優解法。但對於 $n = 8^5$ 就很好選了,這時增長趨勢已經佔主導了。
**Q** 是否存在根據實際使用場景,選擇犧牲時間(或空間)來設計演算法的情況?
在實際應用中,大部分情況會選擇犧牲空間換時間。例如資料庫索引,我們通常選擇建立 B+ 樹或雜湊索引,佔用大量記憶體空間,以換取 $O(\log n)$ 甚至 $O(1)$ 的高效查詢。
在空間資源寶貴的場景,也會選擇犧牲時間換空間。例如在嵌入式開發中,裝置記憶體很寶貴,工程師可能會放棄使用雜湊表,選擇使用陣列順序查詢,以節省記憶體佔用,代價是查詢變慢。
+3 -3
View File
@@ -571,7 +571,7 @@ comments: true
輸入一個 `key` ,雜湊函式的計算過程分為以下兩步。
1. 透過某種雜湊演算法 `hash()` 計算得到雜湊值。
2. 將雜湊值對桶數量(陣列長度)`capacity` 取模,從而獲取該 `key` 對應的陣列索引 `index` 。
2. 將雜湊值對桶數量(陣列長度)`capacity` 取模,從而獲取該 `key` 對應的桶(陣列索引`index` 。
```shell
index = hash(key) % capacity
@@ -610,7 +610,7 @@ index = hash(key) % capacity
index = key % 100
return index
def get(self, key: int) -> str:
def get(self, key: int) -> str | None:
"""查詢操作"""
index: int = self.hash_func(key)
pair: Pair = self.buckets[index]
@@ -619,7 +619,7 @@ index = hash(key) % capacity
return pair.val
def put(self, key: int, val: str):
"""新增操作"""
"""新增和更新操作"""
pair = Pair(key, val)
index: int = self.hash_func(key)
self.buckets[index] = pair
+4
View File
@@ -49,3 +49,7 @@ comments: true
**Q**:為什麼雜湊表擴容能夠緩解雜湊衝突?
雜湊函式的最後一步往往是對陣列長度 $n$ 取模(取餘),讓輸出值落在陣列索引範圍內;在擴容後,陣列長度 $n$ 發生變化,而 `key` 對應的索引也可能發生變化。原先落在同一個桶的多個 `key` ,在擴容後可能會被分配到多個桶中,從而實現雜湊衝突的緩解。
**Q**:如果為了高效的存取,那麼直接使用陣列不就好了嗎?
當資料的 `key` 是連續的小範圍整數時,直接用陣列即可,簡單高效。但當 `key` 是其他型別(例如字串)時,就需要藉助雜湊函式將 `key` 對映為陣列索引,再透過桶陣列儲存元素,這樣的結構就是雜湊表。
@@ -6,7 +6,7 @@ comments: true
<u>堆疊(stack</u>是一種遵循先入後出邏輯的線性資料結構。
我們可以將堆疊類比為桌面上的一疊盤子,如果想取出底部的盤子,則需要先將上面的盤子依次移走。我們將盤子替換為各種型別的元素(如整數、字元、物件等),就得到了堆疊這種資料結構。
我們可以將堆疊類比為桌面上的一疊盤子,規定每次只能移動一個盤子,那麼想取出底部的盤子,則需要先將上面的盤子依次移走。我們將盤子替換為各種型別的元素(如整數、字元、物件等),就得到了堆疊這種資料結構。
如圖 5-1 所示,我們把堆積疊元素的頂部稱為“堆疊頂”,底部稱為“堆疊底”。將把元素新增到堆疊頂的操作叫作“入堆疊”,刪除堆疊頂元素的操作叫作“出堆疊”。