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

参考资料

相关文章
相关标签/搜索