日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

20172332 2017-2018-2 《程序设计与数据结构》第七周学习总结

發(fā)布時間:2025/3/15 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 20172332 2017-2018-2 《程序设计与数据结构》第七周学习总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

20172332 2017-2018-2 《程序設計與數(shù)據(jù)結構》第七周學習總結

教材學習內(nèi)容總結

第十一章 二叉查找樹

  • 1.二叉查找樹:一種帶有附加屬性的二叉樹。即每個結點其左孩子都要小于其父結點,而父結點又小于或等于其右孩子。(左孩子<父結點<=右孩子)
  • 2.二叉查找樹不僅具有二叉樹的操作,還具有以下的特殊操作:

  • 3.用鏈表實現(xiàn)二叉查找樹:每個BinaryTreeNode對象要維護一個指向結點所存儲元素的引用,另外還要維護指向結點的每個孩子的引用。
  • 4.二叉查找樹的構造函數(shù)代碼(引用了父類的兩個構造函數(shù)):
public LinkedBinarySearchTree() {super();}public LinkedBinarySearchTree(T element) {super(element);if (!(element instanceof Comparable))throw new NonComparableElementException("LinkedBinarySearchTree");}
  • 5.addElement操作:
    ①如果這個元素不是Comparable,則該方法會拋出NoComparableElementException異常;
    ②如果樹為空,則這個新元素成為根結點;
    ③如果樹非空,這個新元素會與樹根元素進行比較,
    • (1)如果小于根結點中存儲的元素且根的左孩子為null,則這個元素成為根的左孩子。
    • (2)如果這個新元素小于根結點中存儲的那個元素且根的左孩子不是null,則會遍歷根的左孩子并再次進行比較操作。
    • (3)如果這個新元素大于或等于樹根存儲的那個元素且根的右孩子為null,則這個新元素會成為根的右孩子。
    • (4)如果這個新元素大于或等于樹根處存儲的那個元素且根的右孩子不是null,則會遍歷根的右孩子,并再次進行比較操作。

  • 代碼實現(xiàn):
public void addElement(T element) {if (!(element instanceof Comparable))throw new NonComparableElementException("LinkedBinarySearchTree");Comparable<T> comparableElement = (Comparable<T>)element;if (isEmpty())root = new BinaryTreeNode<T>(element);else {if (comparableElement.compareTo(root.getElement()) < 0){if (root.getLeft() == null) this.getRootNode().setLeft(new BinaryTreeNode<T>(element));elseaddElement(element, root.getLeft());}else{if (root.getRight() == null) this.getRootNode().setRight(new BinaryTreeNode<T>(element));elseaddElement(element, root.getRight());}}modCount++;}private void addElement(T element, BinaryTreeNode<T> node) {Comparable<T> comparableElement = (Comparable<T>)element;if (comparableElement.compareTo(node.getElement()) < 0){if (node.getLeft() == null) node.setLeft(new BinaryTreeNode<T>(element));elseaddElement(element, node.getLeft());}else{if (node.getRight() == null) node.setRight(new BinaryTreeNode<T>(element));elseaddElement(element, node.getRight());}}
  • 6.removeElement操作:(必須推選出另一個結點來代替要被刪除的那個結點)
    ①找不到給定目標元素時,拋出ElementNotFoundException異常。
    ②如果被刪除結點沒有孩子,則replacement返回null。
    ③如果被刪除結點只有一個孩子,則replacement返回這個孩子。
    ④如果被刪除結點有兩個孩子,則replacement會返回中序后繼者(因為相等元素會放到右邊)
  • 代碼實現(xiàn):
public T removeElement(T targetElement) throws ElementNotFoundException {T result = null;if (isEmpty())throw new ElementNotFoundException("LinkedBinarySearchTree");else{BinaryTreeNode<T> parent = null;if (((Comparable<T>)targetElement).equals(root.element)) {result = root.element;BinaryTreeNode<T> temp = replacement(root);if (temp == null)root = null;else {root.element = temp.element;root.setRight(temp.right);root.setLeft(temp.left);}modCount--;}else { parent = root;if (((Comparable)targetElement).compareTo(root.element) < 0)result = removeElement(targetElement, root.getLeft(), parent);elseresult = removeElement(targetElement, root.getRight(), parent);}}return result;}private T removeElement(T targetElement, BinaryTreeNode<T> node, BinaryTreeNode<T> parent) throws ElementNotFoundException {T result = null;if (node == null)throw new ElementNotFoundException("LinkedBinarySearchTree");else{if (((Comparable<T>)targetElement).equals(node.element)) {result = node.element;BinaryTreeNode<T> temp = replacement(node);if (parent.right == node)parent.right = temp;else parent.left = temp;modCount--;}else { parent = node;if (((Comparable)targetElement).compareTo(node.element) < 0)result = removeElement(targetElement, node.getLeft(), parent);elseresult = removeElement(targetElement, node.getRight(), parent);}}return result;}private BinaryTreeNode<T> replacement(BinaryTreeNode<T> node) {BinaryTreeNode<T> result = null;if ((node.left == null) && (node.right == null))result = null;else if ((node.left != null) && (node.right == null))result = node.left;else if ((node.left == null) && (node.right != null))result = node.right;else{BinaryTreeNode<T> current = node.right;BinaryTreeNode<T> parent = node;while (current.left != null){parent = current;current = current.left;}current.left = node.left;if (node.right != current){parent.left = current.right;current.right = node.right;}result = current;}return result;}
  • 7.removeAllOccurrences操作:(使用了contains方法,find方法被重載以便利用二叉查找樹的有序屬性。)
    ①當在樹中找不到指定元素時,則拋出ElementNotFoundException異常
    ②如果指定的元素不是Comparable,則該方法也會拋出ClassCastException異常。
    ③只要樹中還含有目標元素,就會再次調用removeElement方法。
  • 代碼實現(xiàn):
public void removeAllOccurrences(T targetElement)throws ElementNotFoundException {removeElement(targetElement);try{while (contains((T)targetElement))removeElement(targetElement);}catch (Exception ElementNotFoundException){}}
  • 8.removeMin操作:
    ①如果樹根沒有左孩子,則樹根就是最小元素,而樹根的右孩子會變成新的根結點。
    ②如果樹的最左側結點是一片葉子,則這片葉子就是最小元素,這時只需設置其父結點的左孩子引用為null即可。
    ③如果樹的最左側結點是一個內(nèi)部結點,則需要設置其父結點的左孩子引用指向這個將刪除結點的右孩子。
  • 代碼實現(xiàn):
public T removeMin() throws EmptyCollectionException {T result = null;if (isEmpty())throw new EmptyCollectionException("LinkedBinarySearchTree");else {if (root.left == null) {result = root.element;root = root.right;}else {BinaryTreeNode<T> parent = root;BinaryTreeNode<T> current = root.left;while (current.left != null) {parent = current;current = current.left;}result = current.element;parent.left = current.right;}modCount--;}return result;}
  • 9.用有序列表實現(xiàn)二叉查找樹:實現(xiàn)ListADT接口和OrderedListADT接口。
  • 10.BinarySearchTreeList實現(xiàn)的分析:add操作與remove操作都要求重新平衡化樹。
  • 11.樹實現(xiàn)中的有些操作更為有效,有些操作更為低效。
  • 12.蛻化樹:無分支的樹(效率比鏈表還低)
  • 13.平衡樹的方法:
    • (1)右旋(左子樹長):①使樹根的左孩子元素成為新的根元素。②使原根元素成為這個新樹根的右孩子元素。③使原樹根的左孩子的右孩子,成為原樹根的新的左孩子。
    • (2)左旋(右子樹長):①使樹根的右孩子元素成為新的根元素。②使原根元素成為這個新樹根的左孩子元素。③使原樹根右孩子結點的左孩子,成為原樹根的新的右孩子。
    • (3)右左旋(樹根右孩子的左子樹長):①讓樹根右孩子的左孩子,繞著樹根的右孩子進行一次右旋。②讓所得的樹根右孩子繞著樹根進行一次左旋。
    • (4)左右旋(樹根左孩子的右子樹長):①讓樹根左孩子的右孩子繞著樹根的左孩子進行一次左旋。②讓所得的樹根左孩子繞著樹根進行一次右旋。
  • 14.實現(xiàn)二叉查找樹:①AVL樹。②紅黑樹。(自樹根而下的路徑最大長度必須不超過log2 n,而且自樹根而下的路徑最小長度必須不小于log2 n -1)
  • 15.平衡因子:右子樹的高度減去左子樹的高度
  • 16.使樹變得不平衡有兩種方法:①插入結點。②刪除結點。
  • 17.AVL樹的右旋:由下圖可知我們是在結點T的左結點的左子樹上做了插入元素的操作,我們稱這種情況為左左情況,我們應該進行右旋轉(只需旋轉一次,故是單旋轉)【步驟與右旋步驟一樣】

    • 過程:

  • 18.AVL樹的左旋:由下圖可知我們是在結點T的右結點的右子樹上做了插入元素的操作,我們稱這種情況為右右情況,我們應該進行左旋轉(只需旋轉一次,故是單旋轉)【步驟與左旋步驟一樣】

    • 過程:

  • 19.AVL樹的左右(先左后右)旋:如下圖,只是單純的進行一次旋轉,得到的樹仍然是不平衡的。所以應該進行二次旋轉。

  • 20.AVL樹的右左(先右后左)旋:如下圖,只是單純的進行一次旋轉,得到的樹仍然是不平衡的。所以應該進行二次旋轉。

  • 21.紅黑樹:每個結點存出一種顏色(紅色或黑色,通常用一個布爾值來實現(xiàn),false等價于紅色)
    • 紅黑樹的特性:
    • (1) 每個節(jié)點或者是黑色,或者是紅色。
    • (2) 根節(jié)點是黑色。
    • (3) 每個葉子節(jié)點是黑色。 [注意:這里葉子節(jié)點,是指為空的葉子節(jié)點!]
    • (4) 如果一個節(jié)點是紅色的,則它的子節(jié)點必須是黑色的。
    • (5) 從一個節(jié)點到該節(jié)點的子孫節(jié)點的所有路徑上包含相同數(shù)目的黑節(jié)點。
  • 22.紅黑樹的元素添加及刪除。

教材學習中的問題和解決過程

  • 問題1:replacement會返回中序后繼者的中序后繼者是什么東西?
  • 問題1解決方案:從被刪除的結點出發(fā)經(jīng)過它的右結點,然后右結點最左邊的葉子結點就是中序后繼結點。
public Node getSuccessor(Node delNode){ //參數(shù)為被刪除的節(jié)點 //定義一個當前節(jié)點的引用,直接讓往下走一步,走到被刪除節(jié)點的右節(jié)點 Node curr=delNode.right; Node successor=curr; //用來指向中級后續(xù)節(jié)點 Node sucParent=null; //用來指向中級后續(xù)節(jié)點的父節(jié)點 while(curr!=null){ sucParent=successor; successor=curr; curr=curr.left; } //循環(huán)停止,中級后續(xù)節(jié)點被找出 if(successor!=delNode.right){ //將后繼節(jié)點的子節(jié)點(只可能有右節(jié)點)替補到后繼節(jié)點的位置上 sucParent.left=successor.right; //將被刪除的右孩子連接到后繼節(jié)點的右節(jié)點上 successor.right=delNode.right; //將被刪除的左孩子連接到后繼節(jié)點的右節(jié)點上(就是用后繼節(jié)點替換掉被刪除的節(jié)點) } return successor; }
  • 問題引申:為什么要找中序后繼者作為代替刪除結點的位置。
  • 問題引申解決方案:如果直接刪結點,整個樹的大小順序就亂了,所以需要考慮,在樹中找到一個合適的節(jié)點來把這個結點給替換掉,用這種方法來保持整個樹的穩(wěn)定。需要在樹中找出所有比被刪除節(jié)點的值大的所有數(shù),并在這些數(shù)中找出一個最小的數(shù)來。

  • 問題2:AVL樹的作用。
  • 問題2解決方案:刪除時樹的平衡性受到破壞,提高它的操作的時間復雜度。而AVL樹就不會出現(xiàn)這種情況,樹的高度始終是O(lgN).高度越小,對樹的一些基本操作的時間復雜度就會越小。

代碼調試中的問題和解決過程

  • 問題1:紅黑樹的元素添加。
  • 問題1解決方案:
    • 步驟1:將紅黑樹當作一顆二叉查找樹,將節(jié)點插入。
    • 步驟2:將插入的節(jié)點著色為"紅色"。
    • 步驟3:通過一系列的旋轉或著色等操作,使之重新成為一顆紅黑樹。
    private void insert(RBTNode<T> node) {int cmp;RBTNode<T> y = null;RBTNode<T> x = this.mRoot;// 1. 將紅黑樹當作一顆二叉查找樹,將節(jié)點添加到二叉查找樹中。while (x != null) {y = x;cmp = node.key.compareTo(x.key);if (cmp < 0)x = x.left;elsex = x.right;}node.parent = y;if (y!=null) {cmp = node.key.compareTo(y.key);if (cmp < 0)y.left = node;elsey.right = node;} else {this.mRoot = node;}// 2. 設置節(jié)點的顏色為紅色node.color = RED;// 3. 將它重新修正為一顆二叉查找樹insertFixUp(node);}/* * 新建結點(key),并將其插入到紅黑樹中** 參數(shù)說明:* key 插入結點的鍵值*/public void insert(T key) {RBTNode<T> node=new RBTNode<T>(key,BLACK,null,null,null);// 如果新建結點失敗,則返回。if (node != null)insert(node);}
  • 問題2:紅黑樹的元素刪除。
  • 問題2解決方案:
    • 步驟1:將紅黑樹當作一顆二叉查找樹,將節(jié)點刪除。
    • 步驟2:通過"旋轉和重新著色"等一系列來修正該樹,使之重新成為一棵紅黑樹。
    /* * 刪除結點(node),并返回被刪除的結點** 參數(shù)說明:* node 刪除的結點*/private void remove(RBTNode<T> node) {RBTNode<T> child, parent;boolean color;// 被刪除節(jié)點的"左右孩子都不為空"的情況。if ( (node.left!=null) && (node.right!=null) ) {// 被刪節(jié)點的后繼節(jié)點。(稱為"取代節(jié)點")// 用它來取代"被刪節(jié)點"的位置,然后再將"被刪節(jié)點"去掉。RBTNode<T> replace = node;// 獲取后繼節(jié)點replace = replace.right;while (replace.left != null)replace = replace.left;// "node節(jié)點"不是根節(jié)點(只有根節(jié)點不存在父節(jié)點)if (parentOf(node)!=null) {if (parentOf(node).left == node)parentOf(node).left = replace;elseparentOf(node).right = replace;} else {// "node節(jié)點"是根節(jié)點,更新根節(jié)點。this.mRoot = replace;}// child是"取代節(jié)點"的右孩子,也是需要"調整的節(jié)點"。// "取代節(jié)點"肯定不存在左孩子!因為它是一個后繼節(jié)點。child = replace.right;parent = parentOf(replace);// 保存"取代節(jié)點"的顏色color = colorOf(replace);// "被刪除節(jié)點"是"它的后繼節(jié)點的父節(jié)點"if (parent == node) {parent = replace;} else {// child不為空if (child!=null)setParent(child, parent);parent.left = child;replace.right = node.right;setParent(node.right, replace);}replace.parent = node.parent;replace.color = node.color;replace.left = node.left;node.left.parent = replace;if (color == BLACK)removeFixUp(child, parent);node = null;return ;}if (node.left !=null) {child = node.left;} else {child = node.right;}parent = node.parent;// 保存"取代節(jié)點"的顏色color = node.color;if (child!=null)child.parent = parent;// "node節(jié)點"不是根節(jié)點if (parent!=null) {if (parent.left == node)parent.left = child;elseparent.right = child;} else {this.mRoot = child;}if (color == BLACK)removeFixUp(child, parent);node = null;}/* * 刪除結點(z),并返回被刪除的結點** 參數(shù)說明:* tree 紅黑樹的根結點* z 刪除的結點*/public void remove(T key) {RBTNode<T> node; if ((node = search(mRoot, key)) != null)remove(node); }
  • 問題3:按著書上講的左旋右旋步驟來做,會出現(xiàn)錯誤


  • 問題3解決方案:
  • 問題代碼的過程為下圖,很顯然出現(xiàn)了覆蓋結點,導致丟失結點的問題。

  • 改正:


  • 過程:

代碼托管

上周考試錯題總結

  • 無。

點評過的同學博客和代碼

  • 本周結對學習情況
    • 20172326
    • 20172313
    • 結對學習內(nèi)容
      • 教材第11章
  • 上周博客互評情況
    • 20172326
    • 20172313

其他(感悟、思考等,可選)

  • 查找二叉樹是二叉樹的引申學習,難度真的很大!

學習進度條

代碼行數(shù)(新增/累積)博客量(新增/累積)學習時間(新增/累積)重要成長
目標5000行30篇400小時
第一周0/01/12/2
第二周1010/10101/210/12
第三周651/16611/313/25
第四周2205/38661/415/40
第五周967/48332/622/62
第六周1680/65131/734/96
第七周2196/87091/835/131
  • 計劃學習時間:30小時

  • 實際學習時間:35小時

  • 改進情況:AVL樹和紅黑樹真的耗費了大量的時間!

參考資料

  • Java軟件結構與數(shù)據(jù)結構(第4版)
  • 圖解數(shù)據(jù)結構樹之AVL樹
  • 紅黑樹(五)之 Java的實現(xiàn)
  • 平衡二叉搜索樹(AVL樹)的原理及實現(xiàn)源代碼(有圖文詳解和C++、Java實現(xiàn)代碼)

轉載于:https://www.cnblogs.com/yu757503836/p/9873494.html

總結

以上是生活随笔為你收集整理的20172332 2017-2018-2 《程序设计与数据结构》第七周学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。