1. 程式人生 > >二叉樹和雜湊表的優缺點對比與選擇

二叉樹和雜湊表的優缺點對比與選擇

二叉樹(binary tree)和雜湊表(hash table)都是很基本的資料結構,但是我們要怎麼從兩者之間進行選擇呢?他們的不同是什麼?優缺點分別是什麼?

回答這個問題不是一兩句話可以說清楚的,原因是在不同的情況下,選擇的依據肯定也不同。首先來回顧一下這兩個資料結構:

雜湊表使用hash function來對輸入的資料分配index到雜湊表對應的槽中。假設有一個雜湊表的size是100,而我們輸入的資料是從0~99,我們要把輸入資料儲存到雜湊表中。理論上來說,該雜湊表插入和查詢操作的時間複雜度都是O(1)。

二叉樹遵循右子樹大於根節點,左子樹小於根節點的原則進行資料的插入和儲存。如果這個樹的平衡

的,那麼,對於每個元素的插入和查詢操作的時間複雜度是O(log(n)),n是樹的節點個數,log(n)通常是樹的深度。當然,對於不平衡的情況,那就需要更復雜的資料結構的樹(紅黑樹等)進行處理。

上文似乎得出結論雜湊表要好於二叉樹,但是it is not always the case。雜湊表有以下幾個突出的缺點:

  1. 當更多的數插入時,雜湊表衝突的可能性就更大。對於衝突,雜湊表通常有兩種解決方案:第一種是線性探索,相當於在衝突的槽後建立一個單鏈表,這種情況下,插入和查詢以及刪除操作消耗的時間會達到O(n),且該雜湊表需要更多的空間進行儲存。第二種方法是開放定址,他不需要更多的空間,但是在最壞的情況下(例如所有輸入資料都被map到了一個index上)的時間複雜度也會達到O(n)。

  2. 所以,在決定建立雜湊表之前,最好可以估計輸入的資料的size。否則,resize雜湊表的過程將會是一個非常消耗時間的過程。例如,如果現在你的雜湊表的長度是100,但是現在有第101個數要插入。這時,不僅雜湊表的長度可能要擴充套件到150,且擴充套件之後所有的數都需要重新rehash。

  3. 雜湊表中的元素是沒有被排序的。然而,有些情況下,我們希望儲存的資料是有序的。

另一方面,我們討論二叉樹:

  1. 二叉樹不會有衝突(collision),這意味著我們能夠保證二叉樹的插入和查詢操作一直都是O(log(n))的時間複雜度。

  2. 二叉樹的空間佔用跟輸入的輸入資料一致。所以我們不需要為二叉樹預先分配固定的空間。所以,你也不需要預先知道輸入資料的size。

  3. 所有的元素在樹中是排序好的。

Summary

如果你預先知道輸入資料的大小,而且有足夠的空間儲存雜湊表,且不需要對資料進行排序,那麼雜湊表總是好的。因為雜湊表在插入,查詢和刪除操作中只需要常數時間。

另一方面,如果資料是持續的加入,你預先不知道資料的大小,那麼二叉樹是一個折中的選擇。

Reference:
Hash table vs Binary search tree