映射表map(平衡二叉树实现)_手动实现Java集合容器之TreeMap(上)
上一篇我們手寫了HashMap,還有一個很重要的Map的實現類TreeMap。打開源碼第一句話:* A Red-Black tree based {@link NavigableMap} implementation.TreeMap是一個基于紅黑樹的實現。對紅黑樹沒有了解怎么辦,那就先搞清楚紅黑樹的原理。只要理解紅黑樹的玩法,TreeMap實現起來就沒有那么大的難度了。
紅黑樹(Red Black Tree) 是一種自平衡二叉查找樹。所以我們先搞明白什么是二叉查找樹和完美平衡二叉樹。
二叉排序樹(Binary Sort Tree)是具有下列性質的二叉樹:
- 查找:從根結點開始查找,根據每一次比較結果,在當前結點的左子樹與右子樹選擇其一,從而縮小一半的查找范圍。如果到達葉子結點仍然不相等,則查找不成功。
- 插入:首先使用查找算法確定元素的插入位置。如果查找成功,說明相同元素已經存在,則不插入;否則在查找不成功的一條路徑之尾插入結點,作為葉子結點。
- 刪除:a. 葉結點直接刪除 b. 如果被刪除的結點有一個子結點,將子結點移到被刪除的元素的位置。c. 采用中序遍歷(左-根-右),找到待刪除的結點的后繼結點,將其與待刪除的結點互換,然后刪除待刪除的結點。假如我們要刪除29,中序遍歷結果為10-11-13-20-27-29-31-32-39-41-53-50-65-72-91,所以29的后繼結點是31,然后互換位置,刪除29。
- 二叉查找樹的查詢復雜度,和二分查找一樣,插入和查找的時間復雜度均為 O(logn) ,但是在最壞的情況下仍然會有 O(n) 的時間復雜度。原因在于插入和刪除元素的時候,樹沒有保持平衡。
為了降低二叉排序樹的高度,提高查找效率。平衡二叉樹(又稱為AVL樹)。平衡二叉樹(Balanced Binary Tree)是具有下列性質的二叉排序樹:
插入:如果插入一個結點后破壞了二叉樹的平衡性,需要調整一棵最小不平衡子樹。最小不平衡子樹是離插入結點最近,且以平衡因子絕對值大于1的結點為根的子樹。若出現不平衡,則要根據新插入的結點與最低不平衡結點的位置關系進行相應的調整。分為LL,RR,LR,RL四種類型。以下只介紹了最簡單的情況。
LL型:在最低不平衡結點的左孩子的左子樹上插入結點。插入C后,A的平衡因子由1增加到2 。結點B變成新的根結點。A變成右孩子結點,C變成左孩子結點。
RR型:在最低不平衡結點的右孩子的右子樹上插入結點。結點B變成新的根結點。C變成右孩子結點,A變成左孩子結點。
LR型:在最低不平衡結點的左孩子的右子樹上插入結點。結點C變成新的根結點。A變成右孩子結點,B變成左孩子結點。
RL型:在最低不平衡結點的右孩子的左子樹上插入結點。結點C變成新的根結點。B變成右孩子結點,A變成左孩子結點。
平衡二叉樹似乎完美解決了二叉排序樹的問題,通過旋轉使樹的高度最小化,對于有 n 個節點的平衡樹,最壞的查找時間復雜度也為 O(logn)。
那么我們為什么還需要紅黑樹?
因為我們不僅僅需要關心查找的效率,還要考慮插入的效率。因為平衡二叉樹要求每個節點的左子樹和右子樹的高度差至多等于1,這個要求非常嚴格,每次進行插入/刪除數據的時候,幾乎都會破壞這個規則。在插入/刪除數據很頻繁的場景中,平衡二叉樹的性能就會受到很嚴重的影響。所以我們需要紅黑樹。
紅黑樹的定義
- 查找:紅黑樹的查找和二叉排序樹一樣,不再贅述
- 添加:
所以我們發現每一次插入數據之后,如果不滿足紅黑樹的定義,就需要對紅黑樹的結構進行調整。兩種方式:旋轉和重新上色。所以我們在Java源碼中找到了添加數據的方法,并分析這個方法。
/** 假如我們要往這個紅黑數里面添加6沒有調整過的樹是這樣的第一步,8和6兩個同為紅色結點,所以改變顏色,8和14變黑,10變紅。對應源碼中的情況1,當插入結點的叔叔結點為紅,把父結點變黑,叔叔結點也變黑,再把爺爺結點變紅如果插入結點的爺爺結點是右孩子結點,我們找到爺爺結點的父結點,然后在這個結點上左旋,對應源碼中的情況2下一步,右旋,10變黑,20變紅,對應源碼中的情況3從源碼中看出,情況2是情況3的一種擴展。情況4、5、6是1、2、3的鏡像,就不展開了。
刪除也需要調整樹的結構,但是更復雜一些,我們看一下源碼中的方法。
/**刪除一共8種情況,1-4和5-8也是鏡像的,就不舉具體的例子了。TreeMap果然要比HashMap還要復雜的多,就算讀懂了 rebalance的方法,真正實現起來還是有很大的難度。以此為基礎,下一篇我們嘗試一下手寫HashMap。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的映射表map(平衡二叉树实现)_手动实现Java集合容器之TreeMap(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 量化交易_基于Python
- 下一篇: fileinputstream_从Jav