二叉树和哈希表的优缺点对比与选择
二叉樹(binary tree)和哈希表(hash table)都是很基本的數(shù)據(jù)結(jié)構(gòu),但是我們要怎么從兩者之間進(jìn)行選擇呢?他們的不同是什么?優(yōu)缺點(diǎn)分別是什么?
回答這個(gè)問題不是一兩句話可以說清楚的,原因是在不同的情況下,選擇的依據(jù)肯定也不同。首先來回顧一下這兩個(gè)數(shù)據(jù)結(jié)構(gòu):
哈希表使用hash function來對(duì)輸入的數(shù)據(jù)分配index到哈希表對(duì)應(yīng)的槽中。假設(shè)有一個(gè)哈希表的size是100,而我們輸入的數(shù)據(jù)是從0~99,我們要把輸入數(shù)據(jù)儲(chǔ)存到哈希表中。理論上來說,該哈希表插入和查找操作的時(shí)間復(fù)雜度都是O(1)。
二叉樹遵循右子樹大于根節(jié)點(diǎn),左子樹小于根節(jié)點(diǎn)的原則進(jìn)行數(shù)據(jù)的插入和保存。如果這個(gè)樹的平衡的,那么,對(duì)于每個(gè)元素的插入和查找操作的時(shí)間復(fù)雜度是O(log(n)),n是樹的節(jié)點(diǎn)個(gè)數(shù),log(n)通常是樹的深度。當(dāng)然,對(duì)于不平衡的情況,那就需要更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)的樹(紅黑樹等)進(jìn)行處理。
上文似乎得出結(jié)論哈希表要好于二叉樹,但是it is not always the case。哈希表有以下幾個(gè)突出的缺點(diǎn):
當(dāng)更多的數(shù)插入時(shí),哈希表沖突的可能性就更大。對(duì)于沖突,哈希表通常有兩種解決方案:第一種是線性探索,相當(dāng)于在沖突的槽后建立一個(gè)單鏈表,這種情況下,插入和查找以及刪除操作消耗的時(shí)間會(huì)達(dá)到O(n),且該哈希表需要更多的空間進(jìn)行儲(chǔ)存。第二種方法是開放尋址,他不需要更多的空間,但是在最壞的情況下(例如所有輸入數(shù)據(jù)都被map到了一個(gè)index上)的時(shí)間復(fù)雜度也會(huì)達(dá)到O(n)。
所以,在決定建立哈希表之前,最好可以估計(jì)輸入的數(shù)據(jù)的size。否則,resize哈希表的過程將會(huì)是一個(gè)非常消耗時(shí)間的過程。例如,如果現(xiàn)在你的哈希表的長度是100,但是現(xiàn)在有第101個(gè)數(shù)要插入。這時(shí),不僅哈希表的長度可能要擴(kuò)展到150,且擴(kuò)展之后所有的數(shù)都需要重新rehash。
哈希表中的元素是沒有被排序的。然而,有些情況下,我們希望儲(chǔ)存的數(shù)據(jù)是有序的。
另一方面,我們討論二叉樹:
二叉樹不會(huì)有沖突(collision),這意味著我們能夠保證二叉樹的插入和查找操作一直都是O(log(n))的時(shí)間復(fù)雜度。
二叉樹的空間占用跟輸入的輸入數(shù)據(jù)一致。所以我們不需要為二叉樹預(yù)先分配固定的空間。所以,你也不需要預(yù)先知道輸入數(shù)據(jù)的size。
所有的元素在樹中是排序好的。
Summary
如果你預(yù)先知道輸入數(shù)據(jù)的大小,而且有足夠的空間儲(chǔ)存哈希表,且不需要對(duì)數(shù)據(jù)進(jìn)行排序,那么哈希表總是好的。因?yàn)楣1碓诓迦?#xff0c;查找和刪除操作中只需要常數(shù)時(shí)間。
另一方面,如果數(shù)據(jù)是持續(xù)的加入,你預(yù)先不知道數(shù)據(jù)的大小,那么二叉樹是一個(gè)折中的選擇。
Reference:
Hash table vs Binary search tree
轉(zhuǎn)載于:https://www.cnblogs.com/bjwu/p/9823531.html
總結(jié)
以上是生活随笔為你收集整理的二叉树和哈希表的优缺点对比与选择的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入浅出的webpack4构建工具--w
- 下一篇: 牛客网NOIP赛前集训营-提高组(第六场