在執行結束操做後,經過比較每一個結點的平衡因子來維持AVL樹的平衡html
Comparable<T> comparableElement = (Comparable<T>)element
爲何要使用comparable來將element轉爲相關格式呢?java
塗爲紅色,有什麼變化呢?相較於塗爲黑色,黑色結點減小,且其孩子結點爲黑色。若是是黑色呢?該樹總體黑色結點增多。但問題偏偏就在這裏,若是這是一顆單獨的樹還好說,但若是是某一棵樹的子樹呢?只有這一部分的黑色結點增長,別的均不變,這直接致使違反了規定。因此,從中也能夠看出,對於紅黑樹,黑色結點的變化是至關慎重的。從規定插入的結點默認爲紅色也能夠看出這點。git
所以,一開始,個人思路是,經過比較全部元素來肯定一箇中間大小的數據來做爲根。但是,這一實現過程較爲麻煩,須要將當前樹進行重構。翻了翻書,看到大篇幅的旋轉,我就知道應該怎樣作了。能夠看到,每次旋轉,都是由部分到總體,從某一棵失衡的子樹開始,再向上旋轉,再判斷再旋轉。因此,這是一個重複的過程,所以,能夠用遞歸實現。代碼將較爲簡單。算法
if (data.compareTo(p.getElement()) < 0) {//向左子樹尋找插入位置 p.setLeft(insert(data, p.getLeft())); if (height(p.getLeft()) - height(p.getRight()) == 2) {//插入後計算子樹的高度,等於2則須要從新恢復平衡,因爲是左邊插入,左子樹的高度確定大於等於右子樹的高度 //判斷data是插入點的左孩子仍是右孩子 if (data.compareTo(p.getLeft().getElement()) < 0) { //進行LL旋轉 p = singleRotateLeft(p); } else { //進行左右旋轉 p = doubleRotateWithLeft(p); } } }
這裏是部分代碼,所有的有點長,就不進行展現。這裏最爲關鍵的就是這行代碼「 p.setLeft(insert(data, p.getLeft()));
」也就是重複利用遞歸的部分,經過代替循環體,咱們直接鎖定須要插入的位置,在插入結束後,直接就插入結點的父結點的平衡因子來判斷插入是否致使失衡,也就是與2進行判斷,若是違規,直接進行旋轉。這樣一來,在樹的底層位置進行旋轉,儘量縮小涉及到的範圍,也就使得更加便於實現。segmentfault
本章的知識很差理解,尤爲是紅黑樹,涉及了大量的不一樣狀況,使人頭禿,並且網上的知識有漏洞的也不少,繼續本身體會。數據結構
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 0/0 | 1/1 | 3/3 | |
第二週 | 409/409 | 1/2 | 5/8 | |
第三週 | 1174/1583 | 1/3 | 10/18 | |
第四周 | 1843/3426 | 2/5 | 10/28 | |
第五週 | 539/3965 | 2/7 | 20/48 | |
第六週 | 965/4936 | 1/8 | 20/68 | |
第七週 | 766/5702 | 1/9 | 20/88 |