20172308 《程序設計與數據結構》第七週學習總結

教材學習內容總結

第 十一 章 二叉查找樹

1、概述
二叉查找樹是一種含有附加屬性的二叉樹,即其左孩子小於父結點,父結點小於或等於右孩子
(二叉查找樹的定義是二叉樹定義的擴展)
2、 用鏈表實現二叉查找樹html

  • addElement操做:
    addElement方法根據給定元素的值,在樹中的恰當位置添加該元素,若是這個元素不是 comparable,則addElement方法會拋出NoComparableElemementException;
    若是樹爲空,則這個新元素就將成爲根結點;
    若是樹非空,這個新元素會與樹根元素進行比較:
    若是它小於根結點中存儲的那個元素且根的左孩子爲null,則這個新元素就將成爲根的左孩子。
    若是這個新元素小於根結點中存儲的那個元素且根的左孩子不是null,則會遍歷根的左孩子,並再次進行比較操做;
    若是這個新元素大於或等於樹根存儲的那個元素且根的右孩子爲null,則這個新元素會成爲根的右孩子,
    若是這個新元素大於或等於樹根處存儲的那個元素且根的右孩子不是null,則會遍歷根的右孩子,並再次進行比較操做
    如圖:
    java

  • removeElemen操做
    removeElement方法負責從二叉查找樹中刪除給定的 Comparable元素;或者,當在樹中找不到給定目標元素時,則拋出 Element Not FoundException異常;
    與前面的線性結構研究不一樣,這裏不能簡單地經過刪除指定結點的相關引用指針而刪除該結點;
    相反,這裏必須推選出另外一個結點來代替要被刪除的那個結點,受保護方法 replacement返回指向一個結點的引用,該結點將代替要刪除的結點;
    選擇替換結點的三種狀況以下:
  1. 若是被刪除結點沒有孩子,則 replacement返回null
  2. 若是被刪除結點只有一個孩子,則 replacement返回這個孩子
  3. 若是被刪除結點有兩個孩子,則 replacement會返回中序後繼者(由於相等元素會放到右邊)
  • replace方法
    代碼以下:
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;
    }
  • removeAllOccurrences操做
    removeAllOccurrences方法負責從二叉查找樹中刪除指定元素的全部存在;
    或者,當在樹中找不到指定元素時,則拋出 ElementNotFoundException異常;
    若是指定的元素不是Comparable,則removeAllOccurrences方法也會拋出 ClassCastException異常,該方法會調用一次 removeElement方法,以此確保當樹中根本不存在指定元素時會拋出異常,
    只要樹中還含有目標元素,就會再次調用 removeElement方法,注意, removeAllOccurrences方法使用了 LinkedBinaryTree類的 contans方法,還要注意,在 LinkedBinaryTree類中的find方法已經被重載了,以便利用二又查找樹的有序屬性node

  • removeMin操做
    最小元素在二又查找樹中的位置有3種可能情形:
  1. 若是樹根沒有左孩子,則樹根就是最小元素,而樹根的右孩子會變成新的根結點
  2. 若是樹的最左側結點是一片葉子,則這片葉子就是最小元素,這時只需設置其父結點的左孩子引用爲mul便可
  3. 若是樹的最左側結點是一個內部結點,則須要設置其父結點的左孩子引用指向這個將刪除結點的右孩子

3、用有序列表實現二叉查找樹git

  1. 樹的主要使用之一就是爲其餘集合提供高效的實現
  2. 咱們假定 BinarySearchTreeList實現中用到的 LinkedBinarySearchTree實現是一種帶有附加屬性的平衡二叉查找樹,這種附加屬性是:任何結點的最大深度爲log2 n其中n爲樹中存儲的元素數目。
    在咱們的平衡二又查找樹假設之下,add操做和remove操做都要求從新平衡化樹,這一點根據所使用的算法會對分析有所影響。
    另外還要注意一點:雖然樹實現中的有些操做更爲有效,好比 removelast,last和contains,但在利用樹實現時,也有一些操做會變得低效,好比 removeFirst和first

4、平衡二叉查找樹算法

  1. 若是二叉查找樹不平衡,其效率可能比線性結構的還要低
  2. 蛻化樹:看起來更像一個鏈表,但實際上它的效率比鏈表的還低,由於每一個結點還附帶額外的開銷
    如圖(b)所示:
    編程

  3. 平衡化技術
  • 右旋
    要平衡化該樹,咱們須要:
    使樹根的左孩子元素成爲新的根元素
    使原根元素成爲這個新樹根的右孩子元素。
    使樹根的左孩子的右孩子,成爲原樹根的新的左孩子
    數據結構

  • 左旋
    要平衡化該樹,咱們須要:
    使樹根的右孩子元素成爲新的根元素
    使原根元素成爲這個新樹根的左孩子元素。
    使原樹根右孩子結點的左孩子,成爲原樹根的新的右孩子。
    性能

  • 右左旋
    並不是全部的不平衡問題均可以只進行某一種旋轉就能解決
    對於由樹根右孩子的左子樹中較長路徑而致使的不平衡,
    咱們必須先讓樹根右孩子的左孩子,繞着樹根的右孩子進行一次右旋,而後再讓所得的樹根右孩子繞着樹根進行一次左旋
    學習

  • 左右旋
    對於由樹根左孩子的右子樹中較長路徑而致使的不平衡,
    咱們必須先讓樹根左孩子的右孩子繞着樹根的左孩子進行一次左旋,而後再讓所得的樹根左孩子繞着樹根進行一次右旋
    字體

5、實現二叉查找樹:AVL樹

  1. 對於樹中的任何結點,若是其平衡因子(其左右子樹的高度差大於1或小於-1),則以該結點爲樹根的子樹須要從新平衡
  2. 樹只有兩種途徑變得不平衡:插入或刪除結點,所以每次進行這兩種操做後都必須更新平衡因子,而後從操做的結點處檢查樹的平衡性,一直檢查上溯至根結點
    所以:AVL樹一般實現爲每一個結點都包含一個指向其父結點的引用

6、實現二叉查找樹:紅黑樹
(1). 紅黑樹:一種平衡二叉查找樹,其中的每一個結點存儲一種顏色(紅或黑,用布爾值實現,false等價於紅色)
控制結點顏色的規則:

  • 根結點爲黑色
  • 紅色結點的全部孩子都爲黑色
  • 從樹根到樹葉的每條路徑都包含一樣數目的黑色結點

(2). 在某種程度上,紅黑樹的平衡限制沒有AVL樹那麼嚴格,可是,他們的序仍然是logn
(3). 紅黑樹中的元素插入
紅黑樹的插入操做相似於前面的addElement方法,可是這裏老是把插入的新元素顏色設置爲紅色,
插入新元素以後,必要時將從新平衡化該樹,根據須要改變元素的顏色以便維持紅黑樹的屬性

  • 紅黑樹插入元素以後的從新平衡化是一個迭代過程,該迭代過程的終止條件有兩種形式:
形式1:current == root (current是當前正在處理的結點)
咱們老是設置根結點顏色爲黑色,而全部路徑都包括樹根,所以不能違背各條路徑都擁有一樣數目黑色元素這一規則

形式2:current.parent.color == black(即當前結點的父結點顏色爲黑色)
current所指向的結點老是一個紅色結點,這意味着,若是當前結點的父結點是黑色,則可知足全部規則,由於紅色結點並不影響路徑中的黑色結點數目;
另外因爲是從插入點處上溯處理,所以早已平衡了當前結點下面的子樹
  • 從新平衡化的每次迭代,咱們都關注於如何着色當前結點的兄弟結點:
    當前結點的父結點只有兩種可能:左孩子或右孩子

可能一:
若是是左孩子,利用 current.parent.parent.left.color 獲得顏色信息(null元素的顏色爲黑色),且存在兩種狀況:
父結點的兄弟爲紅色或黑色:這兩種狀況下,咱們闡述的處理步驟都將發生在一個循環內部(該循環的終止條件如前所述)
若是父結點的兄弟爲紅色,這時的處理步驟以下:

設置current的父親的顏色爲 black
設置父結點的兄弟的顏色爲black
設置 current的祖父的顏色爲red
設置 current指向current的祖父

若是父結點的兄弟爲黑色,首先要查看current是左孩子仍是右孩子:
若是current是右孩子,則必須設置current等於其父親,在繼續以前還要再向左旋轉current.right;
後面的步驟,與開始時current爲左孩子同樣

若是current是左孩子:
設置current的父親的顏色爲black
設置current的祖父的顏色爲red
若是current的祖父不等於null,則讓current的父親繞着current的祖父向右旋轉

可能二:
若是是右孩子,存在兩種狀況:
父結點的兄弟爲紅色或黑色:這兩種狀況下,咱們闡述的處理步驟都將發生在一個循環內部(該循環的終止條件如前所述)

若是父結點的兄弟爲紅色,這時的處理步驟以下(同當前結點的父結點的兄弟顏色爲紅時):

設置current的父親的顏色爲 black
設置父結點的兄弟的顏色爲black
設置 current的祖父的顏色爲red
設置 current指向current的祖父

若是父結點的兄弟爲黑色,首先要查看current是左孩子仍是右孩子(與當前結點的父結點的兄弟顏色爲黑時,操做對稱):
若是current是左孩子,則必須設置current等於其父親,在繼續以前還要再向右旋轉current.left;
後面的步驟,與開始時current爲右孩子同樣

若是current是右孩子:
設置current的父親的顏色爲black
設置current的祖父的顏色爲red
若是current的祖父不等於null,則讓current的父親繞着current的祖父向左旋轉

(4). 紅黑樹中的元素刪除
與元素插入的那些狀況同樣,刪除的兩種狀況也是對稱的——取決於 current是左孩子仍是右孩子。
當 current爲右孩子時:
(在插入時,咱們最關注的是當前結點的父親的兄弟的顏色)
而對刪除而言,焦點要放在當前結點的兄弟的顏色上(用 current.parent. left.color來指代這種顏色):
還要觀察該兄弟的孩子的顏色,要注意的重要一點是:顏色的默認值是black;
這樣,任什麼時候刻若是試圖取得mull對象的顏色,結果都將是black

其餘的狀況很容易推導出來,只要把上述狀況中的「左」換成「右」、「右」換成「左」便可

若是兄弟的顏色是red,則在作其餘事以前必須完成以下處理步驟:

* 設置兄弟的顏色爲black
* 設置current的父親的顏色爲red
* 讓兄弟繞着 current的父親向右旋轉
* 設置兄弟等於 current的父親的左孩子

下面再繼續處理過程:無論這個初始兄弟是red仍是 black,這裏的處理會根據兄弟的孩子的顏色分紅兩種狀況:
若是兄弟的兩個孩子都是black(或null),則須要

* 設置兄弟的顏色爲red
* 設置 current等於 current的父親

若是兄弟的兩個孩子不全爲black,則將查看兄弟的左孩子是不是black,若是是,則在繼續以前必須完成以下步驟:

* 設置兄弟的右孩子的顏色爲 black
* 設置兄弟的顏色爲red
* 讓兄弟的右孩子繞着兄弟自己向右旋轉
* 設置兄弟等於cumt的父親的左孩子

最後是兄弟的兩個孩子都不爲 black這一狀況,這時必須:

* 設置兄弟的顏色爲 current的父親的顏色。
* 設置 current的父親的顏色爲black
* 設置兄弟的左孩子的顏色爲black
* 讓兄弟繞着 current的父親向右旋轉
* 設置 current等於樹根

該循環終止以後,咱們要酬除該結點,並設置其父親的孩子引用爲mull

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

問題1:紅黑樹這樣設計的意義在哪裏呢?

問題1解析:

如今所明白的是紅黑樹是爲了讓二叉樹路徑不會過長而致使查找等操做的效率太低,經過紅黑結點的限制,使得紅黑樹的最大長度約爲2logn
可是對於紅黑樹的設計思想來源不是很明白,爲何要這樣設計,以及這樣設計真的能達到效果,真的是對的嘛?
像AVL樹那樣,每次插入刪除都要進行旋轉使得樹平衡,這不就夠了嗎?爲何還要再弄一個紅黑樹?

百度了相關的資料,而後總結匯總在這裏:

  • 首先要知道紅黑樹的起源(即設計來源):
    紅黑樹的起源,天然是二叉查找樹了,這種樹結構從根節點開始,左子節點小於它,右子節點大於它
    每一個節點都符合這個特性,因此易於查找,是一種很好的數據結構
    可是它有一個問題,就是容易偏向某一側,這樣就像一個鏈表結構了(如圖),失去了樹結構的優勢,查找時間會變壞

    在這種需求下,平衡樹的概念就應運而生了
    紅黑樹就是一種平衡樹,它能夠保證二叉樹基本符合矮矮胖胖的結構,
    可是理解紅黑樹以前,必須先了解另外一種樹,叫2-3樹,即紅黑樹背後的邏輯(如下2-3樹的介紹來自CSDN博客清晰理解紅黑樹的演變---紅黑的含義
    ____________________________________________________________________________________________________________________________________
    2-3樹是二叉查找樹的變種,樹中的2和3表明兩種節點,如下表示爲2-節點和3-節點。
    2-節點即普通節點:包含一個元素,兩條子連接

3-節點則是擴充版,包含2個元素和三條連接:兩個元素A、B,左邊的連接指向小於A的節點,中間的連接指向介於A、B值之間的節點,右邊的連接指向大於B的節點。

在這兩種節點的配合下,2-3樹能夠保證在插入值過程當中,任意葉子節點到根節點的距離都是相同的。徹底實現了矮胖矮胖的目標。怎麼配合的呢,下面來看2-3樹的構造過程。
所謂構造,就是從零開始一個節點一個節點的插入。
在二叉查找樹中,插入過程從根節點開始比較,小於節點值往右繼續與左子節點比,大於則繼續與右子節點比,直到某節點左或右子節點爲空,把值插入進去。這樣沒法避免偏向問題。在2-3樹中,插入的過程是這樣的。
若是將值插入一個2-節點,則將2-節點擴充爲一個3-節點。
若是將值插入一個3-節點,分爲如下幾種狀況。
(1).3-節點沒有父節點,即整棵樹就只有它一個三節點。此時,將3-節點擴充爲一個4-節點,即包含三個元素的節點,而後將其分解,變成一棵二叉樹。

此時二叉樹依然保持平衡。
(2).3-節點有一個2-節點的父節點,此時的操做是,3-節點擴充爲4-節點,而後分解4-節點,而後將分解後的新樹的父節點融入到2-節點的父節點中去。

(3).3-節點有一個3-節點的父節點,此時操做是:3-節點擴充爲4-節點,而後分解4-節點,新樹父節點向上融合,上面的3-節點繼續擴充,融合,分解,新樹繼續向上融合,直到父節點爲2-節點爲止,若是向上到根節點都是3-節點,將根節點擴充爲4-節點,而後分解爲新樹,至此,整個樹增長一層,仍然保持平衡。
第三種狀況稍微複雜點,爲了便於直觀理解,如今咱們從零開始構建2-3樹,囊括上面全部的狀況,看完因此步驟後,你也能夠本身畫一畫。
咱們將{7,8,9,10,11,12}中的數值依次插入2-3樹,畫出它的過程:

因此,2-3樹的設計徹底能夠保證二叉樹保持矮矮胖胖的狀態,保持其性能良好。可是,將這種直白的表述寫成代碼實現起來並不方便,由於要處理的狀況太多。這樣須要維護兩種不一樣類型的節點,將連接和其餘信息從一個節點複製到另外一個節點,將節點從一種類型轉換爲另外一種類型等等。
所以,紅黑樹出現了,紅黑樹的背後邏輯就是2-3樹的邏輯,可是因爲用紅黑做爲標記這個小技巧,最後實現的代碼量並不大。(可是,要直接理解這些代碼是如何工做的以及背後的道理,就比較困難了。因此你必定要理解它的演化過程,才能真正的理解紅黑樹)

看看紅黑樹和2-3樹的關聯,首先,紅和黑的含義:紅黑樹中,全部的節點都是標準的2-節點,爲了體現出3-節點,這裏將3-節點的兩個元素用左斜紅色的連接鏈接起來,即鏈接了兩個2-節點來表示一個3-節點。這裏紅色節點標記就表明指向其的連接是紅連接,黑色標記的節點就是普通的節點。因此纔會有那樣一條定義,叫「從任一節點到其每一個葉子的全部簡單路徑都包含相同數目的黑色節點」,由於紅色節點是能夠與其父節點合併爲一個3-節點的,紅黑樹實現的實際上是一個完美的黑色平衡,若是你將紅黑樹中全部的紅色連接放平,那麼它全部的葉子節點到根節點的距離都是相同的。因此它並非一個嚴格的平衡二叉樹,可是它的綜合性能已經很優秀了。

【參考資料】
清晰理解紅黑樹的演變---紅黑的含義

代碼運行中的問題及解決過程

問題1:在編寫課後項目PP11.3時,關於removeMax的操做有點理解不到位,如今詳細分析一下代碼,理清思路
問題1解決過程:

二叉查找樹是有特定屬性的,即一個結點的左孩子小於當前結點,當前結點又小於等於其右孩子的
因此一棵樹,最大值必定在樹的最右邊,最小值在樹的最左邊,在此基礎上能夠分析代碼:

  • 首先:判斷是否爲空,空則拋出異常
  • 而後:
    樹不空,判斷樹根的右孩子是否爲空,空則當前根元素即爲最大值;
    樹根的右孩子若是不空的話,就要利用遞歸,一直找到樹最右邊的孩子,返回這個元素,並刪除它
  • 代碼以下:
public T removeMax() {
        T result = null;

        if (isEmpty())
            throw new EmptyCollectionException("LinkedBinarySearchTree");//判斷樹是否爲空,空則拋出異常
        else {//不空的話,則判斷樹根的右孩子是否爲空
            if (root.right == null) {//根的右孩子爲空,則最大值即爲根元素,而後執行刪除根元素操做
                result = root.element;
                root = root.left;//讓根的左孩子等於根,即完成刪除操做
            } else {//根的右孩子不爲空,則執行遞歸操做,一直找到整棵樹最右邊的元素(即最大元素)
                BinaryTreeNode<T> parent = root;
                BinaryTreeNode<T> current = root.right;
                while (current.right != null) {
                    parent = current;
                    current = current.right;
                }
                result = current.element;//找到最大元素current,賦給result
                parent.right = current.left;//把要刪除的元素的左孩子賦給要刪除元素的雙親的右孩子,即完成刪除當前元素的操做
            }

            modCount--;
        }

        return result;
    }

這個刪除最大值的代碼與找最大值最小值的操做findMin,findMax差很少,都是同樣的思路,只是找到以後,不會進行刪除操做而已
以下是找最大值的代碼實現,最小值的實現與之對稱:

public T findMax() {
        T result = null;

        if (isEmpty())
            throw new EmptyCollectionException("LinkedBinarySearchTree");
        else {
            if (root.right == null) {
                result = root.element;
            } else {
                BinaryTreeNode<T> parent = root;
                BinaryTreeNode<T> current = root.right;
                while (current.right != null) {
                    parent = current;
                    current = current.right;
                }
                result = current.element;
            }
        }
        return result;
    }

最後的結果運行如圖:

問題2:課後項目PP11.8,將一顆二叉樹變成一顆AVL樹:如何將一顆二叉樹變成一顆AVL樹?

問題2解決過程:

首先要理解什麼是AVL樹,什麼樣的樹算AVL樹
樹都是用來存儲數據的,普通的二叉樹能夠按照要求在任一能夠放置孩子的結點處放置結點
而AVL樹對放置結點的位置有要求,即放置完後會對結點進行調整,左旋、右旋,使樹達到平衡
而且致使二叉樹失衡的可能只有兩種操做:插入、刪除

因此設計的關鍵在於:如何經過旋轉,使得失衡點處從新平衡

根據書上的介紹,旋轉一共有四種狀況:左旋,右旋,左右旋,右左旋,以知足對失衡點處的失衡狀況的可能性分析
即四種旋轉狀況對應四種可能的失衡狀況:
假設結點X爲失衡點:(原先的二叉樹代碼中沒有刪除操做,這裏也只討論插入帶來的失衡問題)
① 在結點X的左孩子結點的左子樹中插入元素
② 在結點X的左孩子結點的右子樹中插入元素
③ 在結點X的右孩子結點的左子樹中插入元素
④ 在結點X的右孩子結點的右子樹中插入元素

參照上面課本知識梳理中四種旋轉的平衡化技術,對應這四種狀況:第①狀況和第④狀況是對稱的,能夠經過單旋轉來解決,而第②種狀況和第③狀況是對稱的,須要雙旋轉來解決
左單旋代碼實現:

private AVLNode<T> singleRotateLeft(AVLNode<T> x){
    //把w結點旋轉爲根結點
    AVLNode<T> w=  x.left;
    //同時w的右子樹變爲x的左子樹
    x.left=w.right;
    //x變爲w的右子樹
    w.right=x;
    //從新計算x/w的高度
    x.height=Math.max(height(x.left),height(x.right))+1;
    w.height=Math.max(height(w.left),x.height)+1;
    return w;//返回新的根結點
}

右單旋代碼實現:

private AVLNode<T> singleRotateRight(AVLNode<T> w){

    AVLNode<T> x=w.right;

    w.right=x.left;
    x.left=w;

    //從新計算x/w的高度
    w.height=Math.max(height(w.left),height(w.right))+1;
    x.height=Math.max(height(x.left),w.height)+1;

    //返回新的根結點
    return x;
}

利用上面寫好的代碼能夠直接用於雙旋的狀況:
左右旋代碼實現:

private AVLNode<T> doubleRotateWithLeft(AVLNode<T> x){
    //w先進行RR旋轉
    x.left=singleRotateRight(x.left);
    //再進行x的LL旋轉
    return singleRotateLeft(x);
}

右左旋代碼實現:

private AVLNode<T> doubleRotateWithRight(AVLNode<T> x){
    //先進行LL旋轉
    x.right=singleRotateLeft(x.right);
    //再進行RR旋轉
    return singleRotateRight(x);
}

平衡化技術的代碼實現以後,再實現插入操做便可,可是要分兩步(由於是AVL樹嘛):
首先由於是二叉查找樹嘛,確定要對要插入的元素找到合適的位置嘛。。。(這裏跟二叉樹同樣能夠用遞歸算法來找)
而後呢就是平衡判斷,判斷插入元素以後,樹是否平衡(只要評估子樹便可),不平衡則經過上述的四種旋轉來使樹從新平衡

插入操做的代碼以下:

public void insert(T data) {
   if (data==null){
       throw new RuntimeException("data can\'t not be null ");
   }
   this.root=insert(data,root);
}

private AVLNode<T> insert(T data , AVLNode<T> p){

   //說明已沒有孩子結點,能夠建立新結點插入了.
   if(p==null){
       p=new AVLNode<T>(data);
   }else if(data.compareTo(p.data)<0){//向左子樹尋找插入位置
       p.left=insert(data,p.left);

       //插入後計算子樹的高度,等於2則須要從新恢復平衡,因爲是左邊插入,左子樹的高度確定大於等於右子樹的高度
       if(height(p.left)-height(p.right)==2){
           //判斷data是插入點的左孩子仍是右孩子
           if(data.compareTo(p.left.data)<0){
               //進行LL旋轉
               p=singleRotateLeft(p);
           }else {
               //進行左右旋轉
               p=doubleRotateWithLeft(p);
           }
       }
   }else if (data.compareTo(p.data)>0){//向右子樹尋找插入位置
       p.right=insert(data,p.right);

       if(height(p.right)-height(p.left)==2){
           if (data.compareTo(p.right.data)<0){
               //進行右左旋轉
               p=doubleRotateWithRight(p);
           }else {
               p=singleRotateRight(p);
           }
       }
   }
   else
    ;//if exist do nothing
   //從新計算各個結點的高度
   p.height = Math.max( height( p.left ), height( p.right ) ) + 1;

   return p;//返回根結點
}

【參考資料】
二叉樹與AVL樹
java數據結構與算法之平衡二叉樹(AVL樹)的設計與實現

本週錯題

錯題1:

錯題1解析:選擇排序經過重複地將下一個最小的元素放到最後排序的位置來對列表進行排序

錯題2:

錯題2解析:與錯題1重複

錯題3:

錯題3解析:在從二叉搜索樹中刪除元素時,必須提高另外一個節點來替換要刪除的節點。

錯題4:

錯題4解析:與錯題3重複

代碼託管

結對及互評

  • 博客中值得學習的或問題:
    • 侯澤洋同窗的博客排版工整,界面很美觀,而且本週還對博客排版、字體作了調整,很用心
    • 問題總結作得很全面:對課本上不懂的代碼會作透徹的分析,即使能夠直接拿過來用而不用管他的含義
    • 對教材中的細小問題都可以關注,而且主動去百度學習
    • 代碼中值得學習的或問題:
    • 對於編程的編寫總能找到角度去解決
  • 本週結對學習狀況
    • 20172302
    • 結對學習內容
      • 第十一章內容:二叉查找樹

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 0/0 1/1 4/4
第二週 560/560 1/2 6/10
第三週 415/975 1/3 6/16
第四周 1055/2030 1/4 14/30
第五週 1051/3083 1/5 8/38
第六週 785/3868 1/6 16/54
第七週 733/4601 1/7 20/74
相關文章
相關標籤/搜索