2018年學習總結博客總目錄:第一週 第二週 第三週 第四周 第五週 第六週 第七週
html
1.二叉查找樹是一種含有附加屬性的二叉樹,該屬性即其左孩子小於父節點,而父節點又小於等於其右孩子。二叉查找樹的一個示意圖:
在二叉查找樹中:
(01) 若任意節點的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值;
(02) 任意節點的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值;
(03) 任意節點的左、右子樹也分別爲二叉查找樹。git
2.二叉查找樹的接口類繼承自二叉樹的接口類BinaryTreeADT,在其基礎上補充了一些操做方法,代碼以下:算法
public interface BinarySearchTreeADT<T> extends BinaryTreeADT<T> { public void addElement(T element); //往樹中添加一個元素 public T removeElement(T targetElement); // 從樹中刪除一個元素 public void removeAllOccurrences(T targetElement); // 從樹中刪除所指定元素的任何存在 public T removeMin(); //刪除樹中最小元素 public T removeMax(); // 刪除樹中最大元素 public T findMin(); //返回一個指向樹中最小元素的引用 public T findMax(); //返回一個指向樹中最大元素的引用 }
3.鏈表實現二叉查找樹
LinkedBinarySearchTree類它繼承自LinkedBinaryTree類,是對LinkedBinaryTree類的一種拓展,同時它還實現了BinarySearchTreeADT接口類。數據結構
public LinkedBinarySearchTree() { super(); }
public LinkedBinarySearchTree(T element) { super(element); if (!(element instanceof Comparable)) throw new NonComparableElementException("LinkedBinarySearchTree"); }
addElement操做
1.樹空,新元素成爲樹的根結點;
2.非空,與樹根元素進行比較;
(1)小於根元素:①左孩子爲null:新元素成爲根的左孩子;②左孩子不爲null:遍歷根的左孩子,再次進行比較操做;
(2)大於等於根元素:①右孩子爲null:新元素成爲根的右孩子;②右孩子不爲null:遍歷根的右孩子,再次進行比較操做;數據結構和算法
removeElement操做
找到被刪除結點的替換結點,刪除被刪除結點,替換爲替換結點。
選擇替換結點的三種狀況:
(1)被刪除結點沒有孩子,replacement返回null;
(2)被刪除結點有一個孩子,replacement返回這個孩子;
(3)被刪除結點有兩個孩子,replacement返回中序後繼者;(處於根結點右子樹上)
示意圖:
ide
public void removeAllOccurrences(T targetElement) throws ElementNotFoundException { removeElement(targetElement); try { while (contains((T)targetElement)) removeElement(targetElement); } catch (Exception ElementNotFoundException) { } }
4.用有序列表實現二叉查找樹
LinkedBinarySearchTree類有不少方法與有序列表的方法之間存在着一一對應關係函數
5.平衡二叉查找樹
若是二叉查找樹不平衡,那麼其效率可能比線性結構還要低。接下來討論一些經常使用的平衡技術。
(1)右旋
使用條件:根結點左孩子的左子樹過長致使不平衡
使用方法:①樹根左孩子元素成爲新的根元素②原樹根元素稱爲新樹根的右孩子元素③使原樹根左孩子的右孩子,成爲原樹根的新的左孩子
(2)左旋
使用條件:根結點右孩子的右子樹過長致使不平衡
使用方法:①樹根右孩子元素成爲新的根元素②原樹根元素稱爲新樹根的左孩子元素③使原樹根右孩子的左孩子,成爲原樹根的新的右孩子
(3)右左旋
使用條件:根結點的右孩子的左子樹過長致使不平衡
使用方法:①先讓右孩子的左孩子,繞樹根右孩子進行一次右旋②樹根的新的右孩子繞樹根左旋一次
(4)左右旋
使用條件:根結點的左孩子的右子樹過長致使不平衡
使用方法:①先讓左孩子的右孩子,繞樹根左孩子進行一次左旋②樹根的新的左孩子繞樹根右旋一次學習
6.AVL樹
平衡因子:右子樹的高度減去左子樹的高度。.net
平衡因子<-1 | 平衡因子>1 | |
---|---|---|
孩子的平衡因子<=-1 | 右旋 | 右左旋 |
孩子的平衡因子>=1 | 左右旋 | 左旋 |
7.紅黑樹
紅黑樹的特性:
(1)每一個節點或者是黑色,或者是紅色。
(2)根節點是黑色。
(3)每一個葉子節點(Null)是黑色。 [注意:這裏葉子節點,是指爲空(NULL)的葉子節點!]即每一個空結點爲黑色,也即默認結點爲黑色
(4)若是一個節點是紅色的,則它的子節點必須是黑色的。
(5)從一個節點到該節點的子孫節點的全部路徑上包含相同數目的黑節點。
紅黑樹示意圖:
3d
問題1:關於教材242頁中所說的「據此咱們能夠論證具備n個節點紅黑樹的最大高度約爲2*logn」,這句話不能理解,從哪裏論證而來的結果?
問題1解決方案:本身想試着推一下,推的話我想的是從其知足紅黑樹的特徵下手,但試了一會沒有結果,因而就從網上查找資料,給出的一個辦法是用概括總結法去證實這一結論。
"一棵含有n個節點的紅黑樹的最大高度約爲2*logn"等價於「高度爲h的紅黑樹,它的包含的節點個數至少爲2^(h/2)個」。
從某個節點x出發(不包括該節點)到達一個葉節點的任意一條路徑上,黑色節點的個數稱爲該節點的黑高度(x's black height),記爲bh(x)。關於bh(x)有兩點須要說明:
第1點:根據紅黑樹的特性——從一個節點到該節點的子孫節點的全部路徑上包含相同數目的黑節點可知,從節點x出發到達的全部的葉節點具備相同數目的黑節點。這也就意味着,bh(x)的值是惟一的!
第2點:根據紅黑色的特性——若是一個節點是紅色的,則它的子節點必須是黑色的可知,從節點x出發達到葉節點"所經歷的黑節點數目">= "所經歷的紅節點的數目"。假設x是根節點,則能夠得出結論"bh(x) >= h/2"。進而,咱們只需證實 "高度爲h的紅黑樹,它的包含的內節點個數至少爲 2^bh(x)個"便可。
到這裏,咱們將須要證實的定理已經由"一棵含有n個節點的紅黑樹的高度至多爲2log(n)" 轉變成只須要證實"高度爲h的紅黑樹,它的包含的內節點個數至少爲 2bh(x)個"。
下面經過"數學概括法"開始論證高度爲h的紅黑樹,它的包含的節點個數至少爲 2^bh(x)個"。
(01) 當樹的高度h=0時,內節點個數是1,bh(x) 爲1,2^bh(x)也爲 1。顯然,原命題成立。
(02) 當h>0,且樹的高度爲 h-1 時,它包含的節點個數至少爲 2^(bh(x)-1)。這個是根據(01)推斷出來的!
下面,由樹的高度爲 h-1 的已知條件推出「樹的高度爲 h 時,它所包含的節點樹爲 2bh(x)」。
當樹的高度爲 h 時,
對於節點x(x爲根節點),其黑高度爲bh(x)。
對於節點x的左右子樹,它們黑高度爲 bh(x) 或者 bh(x)+1。
根據(02)的已知條件,咱們已知 "x的左右子樹,即高度爲 h-1 的節點,它包含的節點至少爲 2^(bh(x)-1) 個";
因此,節點x所包含的節點至少爲 ( 2^(bh(x)-1) ) + ( 2^(bh(x)-1) ) + 1 = 2^bh(x)。即節點x所包含的節點至少爲 2bh(x)。
所以,原命題成立。
由(01)、(02)得出,"高度爲h的紅黑樹,它的包含的內節點個數至少爲 2^bh(x)個"。
所以,「一棵含有n個節點的紅黑樹的高度至多爲2log(n)」。
問題2:關於紅黑樹的元素插入、刪除
問題2解決方案:
插入
首先,咱們插入的結點設置顏色爲red,若是其父節點爲black,那麼沒有違背紅黑樹任何條件,插入便可,但若是其父節點爲red,那麼須要調整,由於紅色結點的孩子顏色不能爲紅色。
插入一個結點時應該關注其叔叔結點?
由於在父結點爲紅色的狀況下,咱們調整時一定要改動其父結點所構成的樹顏色,而這裏發生改變,那麼必定致使祖父結點處的左右子樹不能再知足「從一個節點到該節點的子孫節點的全部路徑上包含相同數目的黑節點」,那麼咱們須要對叔叔結點也進行改動,才能保持紅黑樹特性。
下面來看須要調整的三種狀況(父結點爲紅色,此時祖父結點必爲黑色,以父結點爲祖父左孩子爲例):
(1)叔叔結點爲紅色
此時咱們須要把叔叔結點d和父親結點b都設爲黑色,這樣不改變祖父結點c下的「從一個節點到該節點的子孫節點的全部路徑上包含相同數目的黑節點」特性;
但還需將祖父c結點設爲紅色(由於在從根結點到祖父往下的路徑上多了一個黑結點),並將當前結點設爲祖父結點,而後往上迭代進行;
(2)叔叔結點爲黑色,且插入結點爲父結點右孩子
此時需將插入結點繞其父結點b向左旋轉,這步不改變樹的各個路徑上的黑結點數目,但仍不知足紅色結點的孩子必爲黑色,此時轉換爲(3)中狀況;
爲何要進行這一步轉化?
由於咱們如今僅靠改變c的左子樹上的顏色是不能保持紅黑樹的特性的。
(3)叔叔結點爲黑色,且插入結點爲父結點左孩子
如今,咱們先繞祖父結點c進行一次右旋,由於祖父結點c爲黑色,此時b結點的右子樹上要多一個黑色結點,同時仍不知足紅色結點孩子都爲黑色;
咱們這時需把b結點設爲黑色,另再將其左右兩個孩子結點a、c設爲紅色。
刪除
刪除操做比較複雜,本身理解還存在一些困難,再也不總結。
參考這篇博客學習紅黑樹的刪除操做
問題1:課本代碼BinarySearchTreeList類出現錯誤,錯誤類型爲both methods have same erasure, yet neither overrides the other。
問題1解決方案:沒見過這個錯誤,去網上查找資料,它的解釋是泛型類型擦除與重載和覆蓋問題,
先看一段代碼
public class Father { void test(Object o){} } class Son<T> extends Father{ void test(T o){}//編譯錯誤! }
這段代碼會報一個編譯錯誤,both methods have same erasure, yet neither overrides the other。
這個錯誤的意思是,兩個方法在類型擦除後,具備相同的原生類型參數列表,可是也不能覆蓋另外一個方法。
泛型類型在編譯後,會作類型擦除,只剩下原生類型。如參數列表中的T類型會編譯成Object,可是會有一個Signature。
儘管兩個test方法具備相同的字節碼,可是類型參數信息用 一個新的簽名(signature) 屬性記錄在類模式中。JVM 在裝載類時記錄這個簽名信息,並在運行時經過反射使它可用。
這就致使了這個方法既不能做爲覆蓋父類test方法的方法,也不能做爲test方法的重載。
看過以後沒感受,不太懂它在說什麼?又看了好幾遍,才終於有些明白,個人那個錯誤也是將個人方法中參數類型改成Object類型,但那樣仍是會報錯,由於它的類型擦除後,父子類兩個重名方法並不能覆蓋。知道這以後,又查看本身的代碼,終於找到了是在個人OrderedListADT類中出了問題,即OrderedListADT類在繼承ListADT類時沒有寫出泛型,改過以後解決問題。
上週代碼行數爲12499行,如今爲13751行,本週共1252行。
上週考試沒有錯題
博客中值得學習的或問題:本週博客內容很是詳細,尤爲是有關紅黑樹的介紹部分以及教材代碼理解部分。
結對學習內容:第十一章——二叉查找樹。
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 0/0 | 1/1 | 15/15 | |
第二週 | 572/572 | 1/2 | 16/31 | |
第三週 | 612/1184 | 1/3 | 13/44 | |
第四周 | 1468/2652 | 2/5 | 13/57 | |
第五週 | 1077/3729 | 1/6 | 14/71 | 初步理解各個排序算法 |
第六週 | 1087/4816 | 1/7 | 17/88 | 認識樹結構 |
第七週 | 1252/6068 | 1/8 | 19/107 | 平衡二叉樹、AVL樹、紅黑樹 |