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

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

學無止境,希望自己可以堅持下去,就算自己有太多的事情也不希望自己落下學習,也希望自己可以活成自己想要的樣子!!加油吧!❤️

教材學習內容總結

《Java軟件結構與數據結構》第十章-樹

一、概述

  • 1、什麼是樹:樹是一種非線性結構,其中的元素被組織成一個層次結構。

  • 2、樹的組成部分:樹由一個包含結點和邊的集構成,其中的元素被存儲在這些結點中,邊則將一個結點和另個結點連接起來。每一結點都位於該樹層次中的某些特定層上。樹的根就是那個位於該樹頂層的唯一結點。(注:一棵樹只有一個根結點。)

  • 3、位於樹中叫底層的結點是上一層結點的孩子。

  • 4、一個結點只有一個雙親,但是一個結點可以有多個孩子。

  • 5、同一雙親的兩個結點稱爲兄弟。

  • 6、根結點是樹中唯一一個沒有雙親的結點。沒有任何孩子的結點稱爲葉子。一個至少有一個孩其實自某一特定結點的路徑可以子的非根結點稱爲一個內部結點。

  • 7、沿着起始自某一特定結點的路徑可以到達的結點是該結點的子孫。

  • 8、結點的層也就是從根結點到該結點的長度。通過計算從根到該結點所必須越過的邊數目,就可以確定其路徑長度。

二、樹的分類

  • 1、對結點所含有的孩子數目無限制的樹稱爲廣義樹。

  • 2、我們將每一結點限制爲不超過n個孩子的樹稱爲一顆n元樹。

  • 3、結點最多具有兩個孩子的樹稱爲二叉樹。(注:含有m個元素的平衡n元樹具有的高度爲lognm。因此一顆含有n個結點的平衡二叉樹具有的高度爲log2m)

  • 4、完全樹:如果某樹是平衡的,且底層所有葉子都位於樹的左邊,則認爲該樹是完全的。(注:完全二叉樹在每個k層上都具有2^k個結點,最後一層除外,在最後一層中的結點必須是最左邊的結點。)
  • 5、滿樹:如果一顆n元的所有的葉子都位於同一層且每一結點要麼是一片葉子要麼正好是具有n個孩子,則稱爲此樹是滿的。

二、實現樹的策略

  • 1、樹的數組實現之計算策略:

    • 一種策略試試用數組來進行存儲一棵樹:對於任何儲存在數組位置n處的元素而言,該元素的左孩子將存儲在位置(2✖️n➕1)處,該元素的右孩子則存儲在位置(2✖️(n➕1))處。
  • 2、樹的數組實現之模擬鏈接策略

    • 模擬了操作系統管理內存的方式。按照先來先服務的基準連續分配數組位置,而不是通過其在樹中的定位將數元素指派到數組位置上。

    • 模擬鏈接策略允許連續分配數組位置而不用考慮該樹的完全性。
  • 3、樹的分析

    • (1)樹是實現其他集合的有用而且有效的方式。

    • (2)一般而言,一顆含有m個元素的平衡n元樹具有的高度爲lognm。

三、樹的遍歷

  • 1、前序遍歷(preorder traversal)

    • (1)順序:從根結點開始,訪問每一結點機及其孩子。

    • (2)圖解:

  • 2、中序遍歷(inorder traversal)

    • (1)順序:從根結點開始,訪問結點的左孩子,然後是該結點,再然後是任何剩餘結點。

    • (2)圖解:

  • 3、後序遍歷(postorder traversal)

    • (1)從根結點開始,訪問結點的孩子,然後是該結點。

    • (2)圖解:

  • 4、層序遍歷(lever-order traversal)

    • (1)從根結點開始,訪問每一層所有的結點,一次一層。

    • (2)圖解:

四、二叉樹

  • 1、ADT:
操作 描述
getRoot 返回指向二叉樹根的引用
isEmpty 判定該樹是否爲空
size 判定樹中數量
contains 判定指針目標是否在該樹中
find 如果找到該指定元素,則返回指向其的引用
toString 返回樹的字符串表示
iteratorInOrder 爲樹的中序遍歷返回一個迭代器
iteratorPreOrder 爲樹的前序遍歷返回一個迭代器
iteratorPostOrder 爲樹的後序遍歷返回一個迭代器
iteratorLeverOrder 爲樹的層序遍歷返回一個迭代器
  • 2、用鏈表實現二叉樹

    • (1)注:每個構造函數必須具有root和count屬性。
  • 3、二叉樹的性質:
    • (1)性質1:在二叉樹的第 i 層上至多有 2^(i-1)個結點 (i >=1)

    • (2)性質2:深度爲 k 的二叉樹至多有2^k -1個結點(k>=1)

    • (3)性質3:對任何一棵二叉樹 T ,如果其終端結點數位n0,度爲2的結點數位n2,則n0=n2+1。

注:

(1) n = n0 + n1 + n2 (結點總數 等於 度爲0 加 度爲1 加 度爲2)

(2) n = n0 + 2*n2 +1(n = 分支總數+1 ;分支總數 = n1+n2 (分支是由度爲1,度爲2的結點射出的))

(3)-(1)得: n0 = n2 + 1

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

  • 問題1:在書中有這樣一句話:

最後一層除外,在最後一層中的結點必須是最左邊的結點。

一開始我並沒有特別理解這個意思是什麼,因爲我的第一意識就是我覺得最後一層都除外了,還提最後一層做什麼?

  • 問題1解決方案:
    在昨天聽了老師講的課以後就知道他所說的是倒數第二層的結點必須是最左邊的結點,這裏也就引進了平衡樹的概念。
    那什麼是平衡樹呢?
    1、平衡樹:它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。
    2、性質:最小二叉平衡樹的節點的公式如下 F(n)=F(n-1)+F(n-2)+1

  • 問題2:在學習使用二叉樹:表達式樹的時候,有這樣一段代碼讓我很是糾結:
 public boolean isOperator() 
    {
        return (termType == 1);
    }

它的實現在下面

if (temp.isOperator())
            {
                operand1 = evaluateNode(root.getLeft());
                operand2 = evaluateNode(root.getRight());
                result = computeTerm(temp.getOperator(), operand1, operand2);
            }
            else
                result = temp.getValue();
        }

就是temp到底是一個什麼類型的值,它如何左右與1和其他之間字符?

  • 問題2解決方法:
    對於我自己是這樣理解的:首先temp.isOperator()這句的作用就是在判斷temp是否是一個操作符,我自己覺得termType == 1只是一個媒介,無論它是否是1都無所謂,那個1只是用於判斷是否爲一個數字,假如不爲一個數字,就判斷其爲一個操作符,假如是操作數的話,就進行繼續遞歸,繼續重複。

  • 問題3:因爲在學習表達式樹的時候就在如何輸出一個數存在着疑問,書本里的代碼繁瑣,讓人很難看下去,爲什麼有契機寫這個問題,是因爲看了侯澤洋同學的博客以後,發現了他很是仔細的寫了每一步的過程,然而我也因爲當時自己代碼實現過程中的一點問題,bug了兩遍這一段程序,也瞭解到大致(後面會寫到那個自己犯的傻瓜問題),在這裏也進行一點記錄。
  • 問題3解決方法:

(1)首先我們從打的包中看到了我們這個方法中用到了四個類,包括之前寫過的一個和本章需要完善的三個,如下

import chapter10.jsjf.BinaryTreeNode;
import chapter10.jsjf.LinkedBinaryTree;
import chapter6.練習題.pp6_8.ArrayUnorderedList;
import chapter6.練習題.pp6_8.UnorderedListADT;

(2)其次我們先要了解整個輸出的過程,假如要輸出一棵樹的話,就得有它的形狀,即如何控制我們所需要的空格,在我自己的計算中,和書中進行了統一,假如一棵樹的層數有k層的話,就是在第0層第一個元素之前有2^k個空格" ";
然後當我們判斷輸出第0層了以後就通過1個或者2個\n進行換行,(ps:兩個會好看一點,就和書中代碼一樣),進行判斷就需要我們將元素和字符分別存入兩個鏈表中,因爲在我bug的時候發現一個問題,就是經常做的一個操作就是將鏈表進行頭刪,返回頭刪的值,這一操作爲的是返回刪除的值進行比較,選擇是否進入判斷語句。然後換行以後,進行同樣的空格,假如遇到元素就要開始進行輸出,轉至(3)。進行新的空格計算,也就是2^(k-1),這個空格間距就是兩個元素之間的空格數目。重複上述過程。

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 + " ";
                }
            }

(3)輸出元素,包括空格和換行符我們都用一個result進行保存,以後再轉至(2)結尾。

f (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 + " ";
            }

        }

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

  • 問題1:在輸出表達式樹的時候,2和1的位置總是跑偏

    我可能花了3個小時一直bug找問題,但是就是找不到

  • 問題1解決:
    我突然意識到可能自己之前寫的添加方法不能用或者有錯,就回去看了一眼,果真不出我所料。。
    ps:之前寫的大致是這樣的:
    就是用了一個while循環,找到最後一個添加進去,最後發現,自己有毒,有個rear不用,總是想着找最後一個,肯定是鏈表敲多了,自己都發現自己被鏈表已經深深的洗腦🤮🤮🤮
    更改以後:

代碼鏈接

上週考試錯題總結

  • 錯題1:
    There are four basic methods for traversing a tree: preorder, inorder, postorder, and level-order.
    A .Top down, bottom up, inorder, and postorder
    B .Top down, inorder, postorder, and level-order
    C .Bottom up, preorder, in order, and postorder
    D .preorder, inorder, postorder, and level-order

    正確答案: D 我的答案: B

錯因:雖然答案已經顯示出來了,但是還是做錯了,我當時對這個題的理解就是去想着那個遍歷順序的方向了,實則沒有想到還能把答案寫出來。

  • 錯題2:
    ___________ traversal means visit the nodes at each level, one level at at time, starting with the root.
    A .preorder
    B .postorder
    C .inorder
    D .level-order

    正確答案: D 我的答案: A

錯因:我剛剛思考了一下我爲什麼選的是A,可能是我當時用了翻譯,翻譯的讓我撒懶,再也不相信谷歌翻譯了。

結對及互評

  • 本週結對學習情況
  • 博客中值得學習的或問題:
    • 內容詳略得當;
    • 代碼調試環節比較詳細;
  • 基於評分標準,我給本博客打分:5分。得分情況如下:
  1. 正確使用Markdown語法(加1分):
  2. 模板中的要素齊全(加1分)
  3. 教材學習中的問題和解決過程, 一個問題加1分
  4. 代碼調試中的問題和解決過程, 一個問題加1分

  • 博客中值得學習的或問題:
    • 內容詳略得當;
    • 代碼調試環節比較詳細;
  • 基於評分標準,我給本博客打分:9分。得分情況如下:
  1. 正確使用Markdown語法(加1分):
  2. 模板中的要素齊全(加1分)
  3. 教材學習中的問題和解決過程, 一個問題加1分
  4. 代碼調試中的問題和解決過程, 一個問題加1分

感悟

本週應該是我覺得全班覺得學習Java第一次很多人都說不懂,所以難說明其重要性,樹,的確是一個樹,給我們帶來了無窮無盡的生機,每天晚上在熬夜寫代碼的時候,就覺得自己真的在納涼,都快被凍死了。
雖然本週過的實在不易,但是終究我們還是把它摳出來了,雖然還是有一些問題,但是總比一竅不通好,我看到了現在班裏呈現出的學習氛圍並沒有那麼強烈了,大家有些人都開始應付作業,應付老師,我覺得實則不該,現在享受以後要享受的時光,以後終究是要還回來的,所以,大家加油,共勉!

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積)
目標 5000行 30篇 400小時
第一週 0/0 1/1 6/6
第二週 1313/1313 1/2 20/26
第三週 901/2214 1/3 20/46
第四周 3635/5849 2/4 20/66
第五週 1525/7374 1/5 20/86
第六週 1542/8869 2/5 25/111

參考資料

藍墨雲班課
Java程序設計
數據結構之平衡樹(Treap)
二叉樹的4種遍歷方法圖解
二叉樹遍歷的遞歸、非遞歸算法(Java實現)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章