2017-2018 20172309第六章學習總結

2017-2018 20172309第六章學習總結

1、教材學習內容總結

  • 什麼是樹?
    • 棧、隊列、列表都是線性結構,而樹是非線性結構
    • 線性結構是一對一的,而樹的特色是一對多
    • 樹由一個包含結點的集組成。
    • 結點與結點之間的鏈接是由邊完成的。
    • 位於樹中較低層次的結點是上一層結點的孩子,沒有任何孩子的結點稱爲葉子
    • 兩個結點之間邊的個數爲其之間的路徑長度
    • 樹的高度是指根到葉子之間最遠路徑的長度。
    • 用圖表示:
  • 樹的分類:
    • 樹中任一結點能夠具備最大孩子的數目,稱爲,按照這個分類標準可分爲:廣義樹、n元樹、二叉樹
    • 平衡樹:樹中全部葉子都位於同一層次或者至少是彼此相差不超過一個層。一個含有m個元素的平衡n元樹具備的高度爲logn(m)
    • 徹底樹:樹是平衡的,且全部葉子都位於左邊。
      html

    • 滿樹:n元樹的全部葉子都位於同一層且每一結點要麼是一片葉子要麼正好具備n個孩子。
      java

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

      這種計算策略是將元素n的左孩子放置於`2n+ 1`、右孩子放置於`2n+2`.其中,n是其雙親的索引。

      舉個例子:

      A的索引爲0,B爲A的左孩子,因此它在數組中的位置在2*0+1=1,因此B在數組中的位置在索引爲1的位置。D爲B的左孩子,B的索引爲1,因此D的索引爲2*1+1=3.git

    • 樹的數組實現之模擬連接策略:數組

      數組中的每一個元素都是一個結點,結點中儲存了每個孩子的索引,好比下圖中A的孩子有兩個B與C,他們的索引分別是2和1,所以2和1就被儲存在了A中。
      安全

  • 樹的遍歷:樹的遍歷主要有4種基本方法:前序遍歷、中序遍歷、後序遍歷和層序遍歷。
    • 前序遍歷:從根節點開始,訪問每個節點及其孩子。好比在上圖的遍歷順序爲:A、B、D、F、E、C。用僞代碼實現爲:
    Visit node;
    Traverse(left child);
    Traverse(right child);
    • 中序排序:從根節點開始,訪問結點的左孩子,而後是該結點,再而後是剩餘任何結點。上圖的遍歷順序爲:D、B、E、F、A、C用僞代碼實現爲:
    Traverse(left child);
    Visit node;
    Traverse(right child);
    • 後續遍歷:從根結點開始,訪問結點的孩子,而後是該結點。上圖的遍歷順序爲:F、D、E、B、C、A。用僞代碼實現爲:
    Traverse(left child);
    Traverse(right child);
    Visit node;
    • 層序遍歷:從根結點開始,訪問每一層的全部的結點,一次一層。上圖的遍歷順序爲:A、B、C、D、E、F。
  • 二叉樹:二叉樹是一種很是重要的數據結構,它同時具備數組和鏈表各自的特色:它能夠像數組同樣快速查找,也能夠像鏈表同樣快速添加。可是他也有本身的缺點:刪除操做複雜markdown

    二叉樹的性質:數據結構

    • 在二叉樹的第i層上至多有2^(i-1)個結點。
    • 深度爲k的二叉樹至多有2^k-1個結點(k≥1),最少有k個結點。
    • 對任何一顆二叉樹,若是其終端結點數爲n0,度爲2的結點數爲n2,則n0=n2+1。
    • 具備n個節點的徹底二叉樹的深度爲[log2n]+1,其中[log2n]+1是向下取整。
    • 若是有一顆有n個節點的徹底二叉樹的節點按層次序編號,對任一層的節點i(1<=i<=n)有:
      • 若是i=1,則節點是二叉樹的根,無雙親,若是i>1,則其雙親節點爲[i/2],向下取整
      • 若是2i>n那麼節點i沒有左孩子,不然其左孩子爲2i.
      • 若是2i+1>n那麼節點沒有右孩子,不然右孩子爲2i+1.
  • 實現二叉樹:
    • 編寫二叉樹的接口(interface)BinaryTreeADT :
    • 使用二叉樹:
    1. 表達式樹
    2. 背部疼痛診斷器
    • 用鏈表實現二叉樹:
    1. BinaryTreeNodeless

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

  • 問題1:跟據中序遍歷的定義:從根結點開始,訪問結點的左孩子,而後是該結點,再而後是任何剩餘的結點。那麼當一個節點只有一個孩子的時候,此時沒有左右孩子之分。那麼是先訪問該結點的孩子,仍是先訪問其餘結點?如圖:當結點爲D時,時先訪問H,仍是訪問E。
  • 個人理解:對於D來講,雖然結點H不是其左孩子,可是對於D來講H、E都是他的剩餘結點,然而H仍是他的孩子,因此H仍是有優先權的。所以上圖的排列順序爲:H、D、B、E、A、F、C、G。
  • 問題2:表達式樹中的打印樹PrintTree()是什麼原理?
  • 問題2解決方案:
    這是一個打印樹的方法:其中while循環每打印一個節點循環一次。舉個例子2 × 3(表達式樹狀)
    • 首先說明:
      • nodes:定義一個列表,用來裝結點。
      • levelList:定義一個列表用來裝結點的層級。
      • printDepth:樹的深度(從零開始數)。
      • countNode:用於記錄輸出結點的個數。
      • currentLevel:當前結點的層級。
      • previousLevel:以前結點的層級。
      • result爲輸出結果。
    • 在第一次循環以前:
      • nodes:×//裏面裝有root結點,即「×」
      • printDepth=1,possibleBodes=4,countNodes=0,currentLevel=0,previouslevel=-1,
      • LevelList:0//裏面裝有0
    • 第一次循環:
      • countNodes=1;
      • current=node(「×」),此時nodes=null;
      • currentLevel= 0,此時LevelList=null;
      • 進入if()語句,出來後result=「__」,previousLevel=0;(注:即只增長了一個空格,換行符自動省略。)
      • 進入下一個if()語句,出來後:result=「__」+ "×";node:2 3;LevelList:1 1;
    • 第二次循環:
      • countNodes=2;
      • current=node(「2」),此時nodes:3;
      • currentLevel=1,此時LevelList:1;
      • 進入if()語句,出來後result=「__」+「×」+「\n」,previousLevel=1;(注:這次增長的空格爲0個,換行符自動省略。)
      • 進入下一個if()語句,出來後:result=「__」+"×"+"\n"+2;node:3,null,null;LevelList:1,2,2;//此次由於結點2沒有左孩子和右孩子,因此nodes進去了兩個null,他們的層級爲2.
    • 第三次循環:
      • countNodes=3;
      • current=node(「3」),此時nodes:null,null;
      • currentLevel=1,此時LevelList:2,2;
      • 進入if()語句,條件不知足,進入else。出來後result="—"+「×」+"\n\n"+"2"+"—"+"—",previousLevel=1;(注:這次增長的空格爲2個。)
      • 進入下一個if()語句,出來後:result="—"+「×」+"\n\n"+"2"+"—"+"—"+"3";node:null,null,null,null;LevelList:,2,2,2,2;//此次由於結點3沒有左孩子和右孩子,因此nodes進去了兩個null,他們的層級爲2.
    • 第四次循環:此後打印出來的都是null,看不到,所以不用討論。
      代碼運行截圖:

      方法代碼:
    public String printTree() //打印樹的代碼。
      {
          UnorderedListADT<BinaryTreeNode<ExpressionTreeOp>> nodes =
              new UnorderedListArrayList<BinaryTreeNode<ExpressionTreeOp>>();//定義一個列表,用來裝結點。
          UnorderedListADT<Integer> levelList = 
              new UnorderedListArrayList<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;
      }
  • 問題三:LinkBinaryTree中要寫迭代器的方法,如何寫?
  • 問題3的解決方法:關於第七章的迭代器,由於這個要寫這個方法。因此先把相關知識總結一下:
    • 首先來看看Java中的Iterator接口是如何實現的:
    package java.util;
    public interface Iterator<E> {
     boolean hasNext();//判斷是否存在下一個對象元素
     E next();//獲取下一個元素
     void remove();//移除元素
    }
    • Iterable:
      1. Java中還提供了一個Iterable接口,Iterable接口實現後的功能是‘返回’一個迭代器
      2. 用代碼實現:
      Package  java.lang;
      import   java.util.Iterator;
      public interface Iterable<T> {
      Iterator<T> iterator();
      }
    • 還能夠用來遍歷集合中的元素。
    Iterator<Book> itr = myList.iterator();
    while(ite.hasnext());
    System.out.println(itr.next());
    還能夠用for——each循環實現:
    java for(Book book:myList)//這兩種方法是同樣的。 System.out.println(book);
    • 還值得注意的是:Iterator遍歷時不能夠刪除集合中的元素!
      • 在使用Iterator的時候禁止對所遍歷的容器進行改變其大小結構的操做。例如: 在使用Iterator進行迭代時,若是對集合進行了add、remove操做就會出現ConcurrentModificationException異常。
      • 由於在你迭代以前,迭代器已經被經過list.itertor()建立出來了,若是在迭代的過程當中,又對list進行了改變其容器大小的操做,那麼Java就會給出異常。由於此時Iterator對象已經沒法主動同步list作出的改變,Java會認爲你作出這樣的操做是線程不安全的,就會給出善意的提醒(拋出ConcurrentModificationException異常)

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

  • 問題1:在測試pp項目代碼正確性時,出現Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to second_term.tenth_chapter.ExpressionTree
  • 問題1解決方案:出現上面的問題的緣由是:在LinkedBinaryTree中的toString方法中的:
UnorderedListADT<BinaryTreeNode<ExpressionTree>> nodes =
                new UnorderedListArrayList<BinaryTreeNode<ExpressionTree>>();
        UnorderedListADT<Integer> levelList =
                new UnorderedListArrayList<Integer>();
        BinaryTreeNode<ExpressionTree> current;

裏面應該用泛型:因此把Expressiontree改成T就OK了。
運行截圖爲:
post

代碼託管

上週考試錯題總結

  • 錯題1:
    _________ traversal means visit the left child, then the node, then the right child.
    A .preorder
    B .postorder
    C .inorder
    D .level-order
  • 理解狀況:
    • 中序排序:先訪問左孩子,而後是該節點,再而後是任何結點。
    • 後續排序:訪問結點的孩子,而後是該結點。
    • 多是點錯了吧。····
  • 錯題2:The simulated link strategy does not allow array positions to be allocated contiguously regardless of the completeness of the tree.
    A .True
    B .False
  • 錯題二理解狀況:用數組模擬鏈表策略,能夠連續分配數組位置。我覺得考點是後面的完整性,沒看到前面的不容許連續分配數組位置。

點評模板:

博客或代碼中值得學習的或問題:

- 內容充實,課本知識講解到位。
- 對於概念的不理解可以深究,提高本身。
- 可是參考資料那一塊,有點敷衍。

本週結對學習狀況

- [20172310](http://www.cnblogs.com/Qiuxia2017/)
- 結對學習內容
    - 第十章:樹
    - 第七章:迭代器;

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

這一章樹對我來講是很難的,書上的不少代碼都是看不懂的。通過問同窗、查資料才明白了很多。還有就是迭代器那一章以前沒有看,如今看了一下。這一週雖然不少做業、可是感受很充實。

學習進度條(上學期截止7200)

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 260/0 1/1 05/05
第二週 300/560 1/2 13/18
第三週 212/772 1/4 21/39
第四周 330/1112 2/7 21/60
第五週 1321/2433 1/8 30/90
第六週 1024/3457 1/9 20/110

參考資料

相關文章
相關標籤/搜索