20172305 2018-2019-1 《Java軟件結構與數據結構》第六週學習總結

20172305 2018-2019-1 《Java軟件結構與數據結構》第六週學習總結

教材學習內容總結

本週內容主要爲書第十章內容:

  • 樹(一種非線性結構,其中的元素被組織成一個層次結構)
    • 結點:樹中的一個位置。
    • :樹中兩個結點的鏈接。
    • 根結點:就是指位於該樹頂層的惟一結點。一棵樹只有一個根結點,根結點沒有父節點。
    • 子結點:一個樹中較低層的結點是上一層結點的子結點。位於樹中當前結點下面的結點,並由邊與之直接鏈接。
    • 同胞結點:屬於同一結點的子結點。
    • 葉結點:沒有任何子結點的結點。
    • 內部節點:一個至少有一個子結點的非根節點。
    • 祖先節點:位於當前結點以上的結點。
    • 後代結點:位於當前結點一下的結點。
    • 路徑長度:經過計算從根到該結點所必須越過的邊數目。
    • 高度:從根到葉子之間的最遠路徑的長度。
    • 階(度):樹中任一結點能夠具備的最大子結點的數目。
  • 樹的分類:
    • 二叉樹:結點最多具備兩個孩子的樹。
    • 徹底樹:若是某樹是平衡的,且底層全部葉子都位於樹的左邊,則認爲該樹是徹底的。
    • 滿樹:若是一顆n元樹的全部葉子都位於同一層且每一結點要麼是一片葉子,要麼是正好具備n個孩子。
    • 徹底二叉樹:在每一個K層上都有2^k個結點,最後一層除外,在最後一層中的結點必須是在最左邊結點。/ 在每一個k層上都具備2^k個結點,最後一層除外,在最後一層中的結點必須是最左的。
    • 平衡樹與非平衡樹
  • 含有m個元素的平衡n元樹具備的高度爲lognm。html

  • 樹的遍歷:
    • 前序遍歷:從根結點開始,訪問每個結點及其孩子。(A->B->D->E->C)
    • 中序遍歷:從根結點開始,訪問結點的左側孩子,而後是該結點,再而後是任何剩餘的結點。(D->B->E->A->C)
    • 後序遍歷:從根結點開始,訪問結點的孩子,而後是該結點。(D->E->B->C->A)
    • 層序遍歷:從根節點開始,訪問每一層的全部結點,一次一層。(A->B->C->D->E)
  • 對於任何存儲在數組位置n處的元素而言,該元素的左結點將存儲在位置2n+1處,該元素的右結點將存儲在位置2(n+1)處。java

  • 模擬連接策略容許連續分配數組位置而不用考慮該樹的徹底性。node

  • 二叉樹--表達式樹表達式樹的及其內部結點包含着操做,且全部葉子也包含着操做數。對操做樹的求值是從下往上的。git

  • 二叉樹--決策樹(背部疼痛診斷器)決策樹的結點表示決策點,其子結點表示在該決策點的可選項。決策樹的葉結點表示可能的判斷,這些推斷是根據決策結果得出的。算法

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

  • 問題1:徹底二叉樹和滿二叉樹的區別?
  • 問題1解決方案:滿二叉樹是徹底二叉樹的一種特殊。故滿二叉樹確定是徹底二叉樹,徹底二叉樹不必定是滿二叉樹。是由於徹底二叉樹倒數第二層的結點能夠有一個子結點(固然是左側節點),能夠有兩個結點,也能夠無子結點。而滿二叉樹則要最後一層的結點數必須爲最大的,這就要求倒數第二層的每一個結點其子結點必須是兩個 即爲滿二叉樹的倒數第二層的結點無葉結點的狀況。
  • 滿二叉樹是指除最後一層外,每一層上的全部結點都有兩個子結點。
    • 若是一顆滿二叉樹的深度爲d,最大層數爲k
    • 它的葉子數是: 2^d
    • 第k層的節點數是: 2^(k-1)
    • 總節點數是: 2^k-1 => (1 + 2 + 4 + 8 ··· + 2^(k-1)的和),其總節點數必定是奇數。
  • 徹底二叉樹是指除最後一層外,每一層上的結點數均達到最大值;在最後一層上只缺乏右邊的若干結點。
  • 徹底二叉樹的判斷方法:葉節點只能出如今最下層和次下層,而且最下面一層的結點都集中在該層最左邊的若干位置的二叉樹
  • 徹底二叉樹的特色是:
    • 只容許最後一層有空缺結點且空缺在右邊,即葉子結點只能在層次最大的兩層上出現。
    • 對任一結點,若是其右子樹的深度爲j,則其左子樹的深度必爲j或j+1。 即度爲1的點只有1個或0個。
  • 問題2:書上表達式樹printTree()代碼如何理解?
  • 問題2解決方案:PostfixEvaluator類的getTree()內容是(treeStack.peek()).printTree()是把樹的形式從棧treeStack的頂部返回出來,再調用Expreesion類中的printTree方法(最噁心的部分),就成一棵樹了。
public String printTree() {
        UnorderedListADT<BinaryTreeNode<ExpressionTreeOp>> nodes = new ArrayUnorderedList<BinaryTreeNode<ExpressionTreeOp>>();
        UnorderedListADT<Integer> levelList = new ArrayUnorderedList<Integer>();

        BinaryTreeNode<ExpressionTreeOp> current;
        String result = "";
        int printDepth = this.getHeight();
        int possibleNodes = (int) Math.pow(2, printDepth + 1);
        int countNodes = 0;

        nodes.addToRear(root);
        Integer currentLevel = 0;
        Integer previousLevel = -1;
        levelList.addToRear(currentLevel);

        while (countNodes < possibleNodes) {
            countNodes = countNodes + 1;
            current = nodes.removeFirst();
            currentLevel = levelList.removeFirst();
            if (currentLevel > previousLevel) {
                result = result + "\n\n";
                previousLevel = currentLevel;
                for (int j = 0; j < ((Math.pow(2, (printDepth - currentLevel))) - 1); j++)
                    result = result + " ";
            } else {
                for (int i = 0; i < ((Math.pow(2,
                        (printDepth - currentLevel + 1)) - 1)); i++) {
                    result = result + " ";
                }
            }
            if (current != null) {
                result = result + (current.getElement()).toString();
                nodes.addToRear(current.getLeft());
                levelList.addToRear(currentLevel + 1);
                nodes.addToRear(current.getRight());
                levelList.addToRear(currentLevel + 1);
            } else {
                nodes.addToRear(null);
                levelList.addToRear(currentLevel + 1);
                nodes.addToRear(null);
                levelList.addToRear(currentLevel + 1);
                result = result + " ";
            }

        }
        return result;
    }
  • 代碼中的兩個無序列表,一個存放的是BinaryTreeNode 類型,就是表達式樹的每個結點;另外一個存放的是Integer類型,用來與以前的無序列表對應,每往無序列表中存放一個結點,就在另外一個無序列表中存入對應的層數。
  • 代碼中的幾個整形變量,printDepth輸出的是高度(從零開始的,實際樹是四層就輸出三層,根結點所在層數爲0),possibleNode經過調用Math的靜態方法pow()來算樹的最大結點數。其中Math.pow(2, printDepth + 1)按照老師講的應該是2^printDepth - 1,可是算法給出的是2^(printDepth+1),實際上咱們調用的getHeight()方法會從第零行開始計算,而在其實是從一層開始的,這樣的話就須要把再加1。而尾部的減1,沒有再此體現。在後面的while循環的條件來看,記錄輸出結點數量的變量 < possibleNodes,這樣的話就可使得記錄輸出結點數量的變量最大狀況等於possibleNodes - 1,這樣就是最大結點數。還有三個整形變量,一個是countNodes,是記錄輸出的結點數目的;一個是currentLevel記錄當前結點所在的層;一個是previousLevel記錄的是當前結點的前一層。
  • 過程:調出根結點A,此時對應的層數是-1,存放到對應的無序列表中。此時,countNodes(輸出的結點數目)的初始值爲0,
    開始第一次進入循環,countNodes加1,調出無序列表中的結點。此時根結點的層數爲0,前一層爲-1,進入第一個條件,換行previousLevel等於currentLevel(兩個變量值都爲0),而後輸出根節點的內容,跳出第一個條件。進入第二個條件,將根結點的左子結點添加到無序列表的尾部,對應的記錄層數的無序列表添加數字1,再將根結點的右子結點添加到無序列表,對應記錄層數的無序列表添加數字1,第一次循環結束。
    進行第二次循環,此時調出根結點的左子結點的內容和左子結點的層數,層數爲1,前一層是0,進入第一個條件,換行previousLevel等於currentLevel(兩個變量值都爲1),而後輸出左子結點的內容,跳出第一個條件。進入第二個條件,往裏面插入左結點的子結點,此時存放節點的無序列表內有和輸出的左結點同一層的右結點,和左結點的兩個子結點,先左節點後右結點,對應的層數應該均爲3,第二次循環結束。
    進行第三次循環,此時調出的是根結點的右子結點和層數,層數和左結點相同也爲1,進入第一個條件(else部分),取消了換行和previousLevel等於currentLevel,這樣的話就和左子結點同行輸出,把根結點的兩個子結點都輸出來了。跳出第一個條件,再將右結點的兩個子結點和對應的層數放到無序列表,其中兩個子結點的層數均爲2,第三次循環結束。
    進行第四次循環,此時調出的根結點的左結點的左子結點,此時對應的層數是2。此時的previousLevel爲1,currentLevel爲2,進入第一個條件的if部分,進行換行並輸出該結點的內容,跳出第一個條件,由於該結點爲空,因此進入第二個條件的else部分,會默認添加該結點的兩個子結點,可是子結點的內容爲空,即插入到無序列表的內容爲空,可是層數會進行增長,第四次循環結束。
    重複進行上述循環(已經調用整個部分的相關代碼,股不在敘述操做),最後達到循環超過該樹的總結點數即possibleNodes跳出循環,輸出result就是整個樹了。express

  • 問題3:背部疼痛診斷器的診斷過程老是回答完一個yes以後就蹦了?
  • 問題3的解決方案:針對這個問題,剛開始只是敲上去而沒有真正去運行。後來聽同窗的運行以後有問題,這纔去運行,結果然有問題。不能轉化爲String,很神奇!!!明明在txt文件內已經有了內容的,就是轉換不成String。剛開始覺得是讀文件的部分有問題,可是沒找到問題,經過單步調試也只是在最後一步有問題。因此,很疑惑!更關鍵的是這個一樣的代碼在別的電腦上會有運行成功的。相同的一段代碼,個人電腦上會提醒有個判斷老是false,而別的上面就沒有。很迷...經過侯澤洋的幫助,是咱們在得到左結點或是右結點時候只是調出其中的內容,該節點的子結點根本沒有調出來致使的,徹底就是個只有該結點的一個樹了,在LinkedBinaryTree中添加幾句就能夠結點的子結點都調出來了。數組

    • 始終有問題的部分:
    • 錯誤圖片:
    • 王文彬提供的代碼(修改位置):
    • 侯澤洋提供的代碼(修改位置):

代碼學習中的問題和解決過程

  • 問題1:鏈表實現的二叉樹的toSring代碼如何編寫?
  • 問題1的解決方案:return super.toString();會出現帶有包名的哈希碼,沒有正常的輸出內容。準備從新書寫的輸出的代碼的時候,發現若是輸出的話就須要用遞歸的方法,來從樹中一層一層的從左往右的按順序輸出。可是若是用到了遞歸的話,註定用String類型的變量輸出不出來(由於要進行一個疊加的過程,而設置變量的話也不能在此方法下進行輸出。須要像以前的那個歸併排序和快速排序同樣,一個進行遞歸的主要方法,另外一個調用該遞歸方法,來達到代碼的實現。)圖過期用遞歸來實現的話,就能夠運用不一樣的遍歷方式。經過書上代碼--表達式樹的輸出樹狀形式,就直接搬過來實現toString方法(相關代碼分析在教材分析總結)。數據結構

    • 產生帶包名哈希碼:
    • 前序輸出:從根結點開始,訪問每個結點及其子結點。因此,先調出根結點的內容,而後從左結點開始調出至右結點的內容。
    • 中序輸出:從根結點開始,先訪問結點的左子結點的內容,在調出該結點的內容,再訪問結點的右子結點的內容。
    • 後序輸出:從根結點開始,先訪問該結點的子結點的內容,在退回到結點的內容。
    • 層序輸出:從根節點開始,每一層的從左到右的進行輸出。
    • 樹狀輸出(借鑑表達式樹的形式):

  • 問題2:表達式樹的輸出爲何老是輸出不對?
  • 問題2解決方案:書上表達式樹的代碼在進行樹的輸出時候,總會輸出的稀亂稀亂的一堆,代碼也沒有爆紅。第一次經過單步調試發現,是本身的getHeight()方法的方法體沒有寫,致使輸出的結果老是0。還要本身修改getHeight()...悲慘自行補了相關代碼,先判斷樹是否是空的,不空的話經過PP10.3作的代碼,進行判斷是不是葉結點進行循環遍歷,在遍歷的過程當中進行計數。可是在輸出樹的狀況下就是缺最後一行,經過嘗試對一個已知高度的樹調用getHeight()方法時,在輸出的時候發現會比實際高度少1,因此在計數變量的初始值從0改成1嘗試一下,結果就完整了。學習

    • 第一次修改:
    • 第二次修改:
    • 第三次修改:
  • 問題3:removeRightSubtree、removeAllElement和contains方法
  • 問題3解決方案:
    • 針對removeRightSubtree方法以爲須要先進行遍歷,每遍歷一個再刪除一個,直到完成任務。後來想一想以爲好麻煩,還要進行迭代。想出一個簡單粗暴的方法,就是已經肯定刪除右枝杈了,那麼就直接把節點的右側枝杈直接改成null就能夠了,根本不用管其內容就是刪。可是,作出的第一個版本,是刪除根結點的右側,那麼若是想刪除某個節點的右側,這樣的話方法就不會起做用。因此,改進了此方法以實現能夠刪除某一個節點的右子結點。
    • 針對removeAllElement方法,由於實現前一個方法時簡單粗暴,而此方法和以前的有必定的相似,因此直接就從新定義一個BinaryTreeNode 類的根結點,讓其爲零,再使這個結點替代以前有內容的樹就能夠了。
    • 針對contains方法,這個方法是判斷指定目標是否在該樹上。由於以前有書上的find方法做支撐,就經過該方法查找出是否有指定元素,若是就輸出true,沒有就false。

代碼託管

上週考試錯題總結

無錯題,終於不用錯題總結了...this

結對與互評

點評(王禹涵)

  • 博客中值得學習的或問題:
    • 背景圖很好看,可是截圖內容看得不是很清晰。問題2的代碼也進行了註釋,是我應該學習的地方。
  • 代碼中值得學習的或問題:
    • 代碼圖片也是看的不清晰,問題提的很好,問題2出現的是哈希碼,建議能夠嘗試這用四種遍歷順序輸出,或是像樹那樣輸出。
  • 基於評分標準,我給本博客打分:8分。
    • 得分狀況以下:
    • 正確使用Markdown語法(加1分)
    • 模板中的要素齊全(加1分)
    • 教材學習中的問題和解決過程, 兩個問題加2分
    • 代碼調試中的問題和解決過程, 兩個問題加2分
    • 感想,體會不假大空的加1分
    • 點評認真,能指出博客和代碼中的問題的加1分

點評(方藝雯)

  • 博客中值得學習的或問題:
    • 圖片特別細緻清晰,並且針對實現樹的策略寫的很詳細,針對printTree方法能夠更進一步的描述運算過程。
  • 代碼中值得學習的或問題:
    • 代碼問題記錄詳細,第二個問題我也遇到過。建議在插圖的時候能夠添加多一點的文字描述,沒有什麼大問題,寫的很棒棒。
  • 基於評分標準,我給本博客打分:10分。
  • 得分狀況以下:
    • 正確使用Markdown語法(加1分)
    • 模板中的要素齊全(加1分)
    • 教材學習中的問題和解決過程, 二個問題加2分
    • 代碼調試中的問題和解決過程, 四個問題加4分
    • 感想,體會不假大空的加1分
    • 點評認真,能指出博客和代碼中的問題的加1分

互評對象

感悟

第十章的樹學起來很費勁,徹底的一個接着一個,沒有順序,沒有結構的(二叉樹還好點)。課後的代碼相對簡單,可是書上的示例代碼寫的比課後代碼還麻煩。很是感謝侯澤洋的幫助,幫助我更好的理解樹的相關知識,有些代碼的問題是在幫助下完成的,這也顯示出個人不足,沒有更好的掌握知識,邏輯的相關內容只有本身弄懂才行,別人的幫助只是輔助的。起初還感受前面代碼相對簡單,但那是到了樹的部分真是欲哭無淚的感受。只能再好好的學習學習再學習了。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 0/0 1/1 15/15
第二週 703/703 1/2 20/35
第三週 762/1465 1/3 20/55
第四周 2073/3538 1/4 40/95
第五週 981/4519 2/6 40/135
第六週 1088/5607 2/8 50/185

參考資料

相關文章
相關標籤/搜索