本週學習了第11章二叉查找樹php
操做 說明 addElement 往樹中添加一個元素 removeElement 從樹中刪除一個元素 removeAllOccurrences 從樹中刪除所指定元素的任何存在 removeMin 刪除樹中的最小元素 removeMax 刪除樹中的最大元素 findMin 返回一個指向樹中最小元素的引用 findMax 返回一個指向樹中最大元素的引用
右旋:右旋能夠解決樹根左孩子的左子樹中較長的路徑而致使的不平衡
html
右旋的三步
1.使樹根的左孩子元素成爲新的根元素
2.使原根元素成爲這個新樹根的右孩子元素
3.使原樹根的左孩子的右孩子,成爲原樹根的新的左孩子node
左右旋git
規則以下web
根結點爲黑色 紅色結點的全部孩子爲黑色 從樹根到樹葉的每條路徑都包含一樣數目的黑色結點
根據被插入節點的父結點的狀況,能夠將"當節點z被着色爲紅色結點,並插入二叉樹"劃分爲三種狀況來處理。算法
① 狀況說明:被插入的結點是根結點。 處理方法:直接把此結點塗爲黑色。 ② 狀況說明:被插入的結點的父結點是黑色。 處理方法:什麼也不須要作。結點被插入後,仍然是紅黑樹。 ③ 狀況說明:被插入的結點的父結點是紅色。 處理方法:那麼,該狀況與紅黑樹的特性「從一個結點到該結點的子孫結點的全部路徑上包含相同數目的黑結點。」相沖突。這種狀況下,被插入結點是必定存在非空祖父結點的;進一步的講,被插入結點也必定存在叔叔結點(即便叔叔結點爲空,咱們也視之爲存在,空結點自己就是黑色結點)。理解這點以後,咱們依據"叔叔結點的狀況",將這種狀況進一步劃分爲3種狀況(Case)。
/ | 現象說明 | 處理策略 |
---|---|---|
case1 | 當前結點的父結點是紅色,且當前結點的祖父結點的另外一個子結點(叔叔結點)也是紅色。 | (01) 將「父結點」設爲黑色。(02) 將「叔叔結點」設爲黑色。(03) 將「祖父結點」設爲「紅色」。(04) 將「祖父結點」設爲「當前結點」(紅色結點);即,以後繼續對「當前結點」進行操做。 |
case2 | 當前結點的父結點是紅色,叔叔結點是黑色,且當前結點是其父結點的右孩子 | (01) 將「父結點」做爲「新的當前結點」。(02) 以「新的當前結點」爲支點進行左旋。 |
case3 | 當前結點的父結點是紅色,叔叔結點是黑色,且當前結點是其父結點的左孩子 | (01) 將「父結點」設爲「黑色」。(02) 將「祖父結點」設爲「紅色」。(03) 以「祖父結點」爲支點進行右旋。 |
當父親是左孩子的時候
兩種運行是對稱的數據結構
若是叔叔的顏色是redpost
設置叔叔的顏色爲black 設置current的父親顏色爲red 讓叔叔繞着current的父親向右旋轉 設置叔叔等於current父親的左孩子 若是叔叔的兩個孩子都是black或者null則須要設置叔叔的顏色爲red,設置current等於current的父親 若是叔叔的兩個孩子不全爲black,若是叔叔的左孩子是black,則設置右孩子也爲black,設置叔叔的顏色爲red,再讓兄弟的右孩子繞着兄弟自己向右旋轉,最後設置叔叔等於current父親的左孩子 若是叔叔的兩個孩子都不爲black,則設置叔叔的顏色爲current父親的顏色,設置current父親的顏色爲black,設置叔叔的左孩子的顏色爲black,讓叔叔繞着current的父親向右旋轉,設置current等於樹根。 循環終止後刪除該結點,設置其父親的孩子引用爲null
if (current == null) throw new ElementNotFoundException("LinkedBinaryTree");
爲何仍是會出現這樣的問題?學習
current == root
,二是current.parent.color == black
是如何執行的,同時按照書上的圖示,紅黑樹平衡以後,樹的結構彷佛沒有發生改變,那麼是在什麼地方實現了平衡?問題1:PP11.8在二叉樹的基礎上完成AVL樹的方法,其中關於左旋右旋等方法如何用代碼實現。測試
private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> k2) { AVLTreeNode<T> k1; k1 = k2.left; k2.left = k1.right; k1.right = k2; k2.height = max( height(k2.left), height(k2.right)) + 1; k1.height = max( height(k1.left), k2.height) + 1; return k1; }
如圖,該樹不平衡時,將整個左子樹繞着k2點進行旋轉,k1是k2的左孩子,因而k1成爲新的根結點,k1的右孩子成爲k2的左孩子,k2設置爲k1的右孩子。以後再從新定義k一、k2的高度,k2從左右子樹中選出較長的一支做爲其高度,加一是由於樹的高度從0開始。k1也是從它的左右子樹中取出較長一支,但這裏的右子樹能夠直接調用k2的高度。
再分析一下右左旋的狀況
private AVLTreeNode<T> leftRightSpin(AVLTreeNode<T> node) { node.left = rightRightSpin(node.left); return leftLeftSpin(node); }
原理便是讓初始結點的右孩子的左孩子繞初始結點的右孩子進行一次右旋node.left = rightRightSpin(node.left);
,再讓初始結點的右孩子繞着初始結點進行一次左旋return leftLeftSpin(node);
。
相似地能夠寫出右旋和左右旋的方法,可是何時調用右旋,何時進行左右旋的方法尚未進行定義。以添加元素爲例,這裏編寫了一公一私兩個方法
public void addElement(T key) { root = addElement(root, key); } private AVLTreeNode<T> addElement(AVLTreeNode<T> tree, T element) { if (!(element instanceof Comparable)) { throw new NonComparableElementException("AVLTreeNode"); } if (tree == null) { // 新建節點 tree = new AVLTreeNode<T>(element, null, null); if (tree==null) { throw new EmptyCollectionException("EmptyCollectionException"); } } else { if (element.compareTo(tree.getElement()) < 0) { // 應該將key插入到"tree的左子樹"的狀況 tree.left = addElement(tree.left, element); // 插入節點後,若AVL樹失去平衡,則進行相應的調節。 if (height(tree.right) - height(tree.left) == -2) {//由於查到左子樹,必然左側感度大於右側暗度 if (element.compareTo(tree.left.getElement()) < 0) tree = leftLeftSpin(tree); else tree = leftRightSpin(tree); } } else if (element.compareTo(tree.getElement()) >= 0) { // 應該將key插入到"tree的右子樹"的狀況 tree.right = addElement(tree.right, element); // 插入節點後,若AVL樹失去平衡,則進行相應的調節。 if (height(tree.left) - height(tree.right) == -2) { if (element.compareTo(tree.right.getElement()) > 0) tree = rightRightSpin(tree); else tree = rightLeftSpin(tree); } } } tree.height = Math.max( height(tree.left), height(tree.right)) + 1; return tree; }
最後打印樹的方法調用了EXpressionTree的PrintTree方法,結果以下
上週的測試彷佛都是錯在沒有看清楚單詞-_-||
中文 | 英文 |
---|---|
前序遍歷 | preorder traversal |
中序遍歷 | inorder traversal |
後序遍歷 | postorder traversal |
層序遍歷 | level-order traversal |
基於評分標準,我給譚鑫的博客打分:8分。得分狀況以下:
正確使用Markdown語法(加1分):
模板中的要素齊全(加1分)
教材學習中的問題和解決過程, 一個問題加1分
代碼調試中的問題和解決過程, 五個問題加5分
基於評分標準,我給方藝雯的博客打分:6分。得分狀況以下:、
正確使用Markdown語法(加1分):
模板中的要素齊全(加1分)
教材學習中的問題和解決過程, 三個問題加3分
代碼調試中的問題和解決過程, 一個問題加1分
教材學習在紅黑樹這個地方卡了殼,前思後想左思右想地看教材上的講解,一邊寫博客一邊想一邊提出疑問,致使寫了一大堆囉嗦話,但是最終也沒有理得太順,也不知道我挑的教材上出現的錯誤是否是隻是我沒有理解到他真正的意圖。
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 0/0 | 1/1 | 8/8 | |
第二週 | 470/470 | 1/2 | 12/20 | |
第三週 | 685/1155 | 2/4 | 10/30 | |
第四周 | 2499/3654 | 2/6 | 12/42 | |
第六週 | 1218/4872 | 2/8 | 10/52 | |
第七週 | 590/5462 | 1/9 | 12/64 | |
第八週 | 993/6455 | 1/10 | 12/76 |