20182311 2019-2020-1 《数据结构与面向对象程序设计》第9周学习总结

正文

20182311 2019-2020-1 《数据结构与面向对象程序设计》第9周学习总结

教材学习内容总结

教材第15章

  • 树的概述
    1. 定义:树是一种非线性结果,元素按分层组织。它含有结点和连接结点的边,位于树最高层的是根节点root,结点相对于根节点的位置表示结点的层。树中不含有子节点的结点为叶结点,除叶结点和根结点外的其他结点都是内节点。
    2. 树的阶:结点含有的最大子结点数。
    3. 路径长度:连接两个结点边的数量。高度:从根结点到叶结点的最长路径的长度。
    4. n元树:任一结点的子节点数目不多于n的
    5. 平衡:所有叶结点都位于同一层
    6. 完全:树平衡,且最底层的叶结点都在树的左边
  • 树的实现:
    1. 数组实现策略:使用数组实现树,数组下标为n的结点的左子树下标为2n,右子树下标为2n+1。思路简单,访问迅速,但是该数组会为不含数据的树位置分配空间,浪费存储空间。
    2. 模拟连接策略:在数组中存入孩子的数组索引,为了节省空间会增加删除树中元素时,数组元素进行移位的成本。
    3. 链表实现:链表是最常见的造树方法,二叉链表可连接左右节点,三叉链表可指向父节点,多叉链表可以指向更上一级或者siblings
  • 树的遍历:递归遍历比非递归遍历更简单,参照一个顺序的遍历可以写出其他顺序的遍历。
    • 前序遍历:先根节点,后左子树,再右子树
    • 中序遍历:先左子树,后根节点,再右子树
    • 后序遍历:先左子树,后右子树,再根节点

  • 非递归遍历示例(先序):
public void preorderTraverse(){
      //非递归实现先序遍历
      Node t=root;
      Node top;
          Stack<Node> stack=new Stack<Node>();
          while(t!=null||!stack.isEmpty()){
              while(t!=null){
                  System.out.print(t.getData()+"\t");
                  stack.push(t);
                  t=t.getLeft();
              }
              top=(Node)stack.peek();
              stack.pop();
              t=top.getRight();
          }
      }
  • 递归遍历示例(先序):
public static void preOrderRe(Node t)
  {//递归实现前序遍历
      System.out.print(t.getData()+"\t");
      Node leftTree = t.getLeft();
      if(leftTree != null){
          preOrderRe(leftTree);
      }
      Node rightTree = t.getRight();
      if(rightTree != null){
          preOrderRe(rightTree);
      }
  }
  • 非递归遍历示例(中序):
public void midorderTraverse(){
      //非递归实现中序遍历
      Node t=root;
      Stack<Node> stack=new Stack<Node>();
      while(t!=null||!stack.isEmpty()){
          while(t!=null){
              stack.push(t);
              t=t.getLeft();
          }
          t=(Node)stack.peek();
          stack.pop();
          System.out.print(t.getData()+"\t");
          t=t.getRight();
      }
  }

  • 递归遍历示例(中序):
 public static void midOrderRe(Node t)
  {//递归实现中序遍历
      Node leftTree = t.getLeft();
      if(leftTree != null){
          midOrderRe(leftTree);
      }
      System.out.print(t.getData()+"\t");
      Node rightTree = t.getRight();
      if(rightTree != null){
          midOrderRe(rightTree);
      }
  }
  • 非递归遍历示例(后序):
public void lasorderTraverse(){
      //非递归实现后序遍历
      Node t=root;
      Node top,last=null;
      Stack<Node> stack=new Stack<Node>();
      while(t!=null||!stack.isEmpty()){
          while(t!=null){
              stack.push(t);
              t=t.getLeft();
          }
          top=(Node)stack.peek();
          if(top.getRight()==null||top.getRight()==last){
              stack.pop();
              System.out.print(top.getData()+"\t");
              last=top;
          }
          else{
              t=top.getRight();
          }
      }
  }
  • 递归遍历示例(后序):
public static void lasOrderRe(Node t)
  {//递归实现后序遍历
      Node leftTree = t.getLeft();
      if(leftTree != null){
          lasOrderRe(leftTree);
      }
      Node rightTree = t.getRight();
      if(rightTree != null){
          lasOrderRe(rightTree);
      }
      System.out.print(t.getData()+"\t");
  }
  • 层序遍历:
public void seqTraverse(Node t){
      //利用队列先进先出实现层级遍历
      Queue<Node> queue=new LinkedList<Node>();
      queue.add(t);
      while(!queue.isEmpty()){
          Node q=queue.peek();
          queue.remove();
          if(q.getLeft()!=null){
              queue.add(q.getLeft());
          }
          if(q.getRight()!=null){
              queue.add(q.getRight());
          }
          System.out.print(q.getData()+"\t");
      }
  }
  • 决策树:基于链树实现,将决策信息填入结点中,定义一个访问方法,设置判定条件为输入n即访问左子树,输入y即访问右子树。

教材第16章

  • 二叉查找树的概述:
    • 定义:二叉查找树在二叉树的基础上规定了,左孩子小于父节点,父节点又小于等于右孩子。
    • 具体过程:


  • 一些方法:addElement、removeElement(不能简单的删除节点的相关引用指针,而是要寻找替代点),replacement(寻找替代点的方法,若结点没有孩子,返回空;若结点只有一个孩子,返回这个孩子;若结点有两个孩子,返回他的后继/前继结点),后继就是按顺序排列后他的后面一位,前继就是按顺序排列后他的前面一位。这两个结点一定没有孩子,否则就不是前继/后继结点(分别位于左子树的最右边和右子树的最左边)
  • 一些异常:树中元素不是Comparable,addElemnt会抛出NoComparableElementException异常。

教材学习中的问题和解决过程

  • 问题1:怎样实现从子结点返回到根结点?或者说建立虚空结点树的时候,遇到#返回null以后怎么回到根节点重新赋值?
  • 问题1解决方案:尝试了两种方法,一种是建立三叉链表,能实现就是有点麻烦。递归的思想其实就包括返回上一级,所以直接使用递归就能实现。

代码调试中的问题和解决过程

  • 问题1:返回空指针异常和0>1错误

  • 问题1解决方案:习惯规定search方法未找到元素返回-1,造成copyOf里面会出现(0,1)的情况。把未找到元素的返回值设置为1即可。

代码托管

上周错题总结

  • One of the uses of trees is to provide simpler implementations of other collections.
    A .True
    B .Flase
  • 正确答案: B 我的答案: A
  • To maintain the completeness of the tree, there is only one valid element to replace the root, and that is the element stored in the first leaf in the tree.
    A .True
    B .Flase
  • 正确答案: B 我的答案: A 。
  • 用最后一个叶子节点替代。
  • The removeMin operation for both the linked and array implementations is O(log n).
    A.True
    B .Flase
  • 正确答案: A 我的答案: B。
  • 链表实现的需要遍历到最小值移除,数组实现的应该要考虑删除最小值后的移位。
  • In a linked implementation of a stack, a pushed element should be added to the end of the list.
    A .true
    B .false
  • 正确答案:B 我的答案:A。
  • 在堆栈的链接实现中,应该在列表的前面添加一个push元素。如果元素被添加到列表的末尾,那么pop操作将需要线性时间,因为我们需要遍历整个元素以获得指向列表中最后一个元素的指针。链接实现和数组实现有一定区别。

结对及互评

点评过的同学博客和代码

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 10000行 30篇 400小时
第一周 246/246 2/2 30/30 初步掌握linux命令、java小程序和jdb调试
第二周 73/319 3/3 30/60
第三周 906/1225 3/6 20/80
第四周 748/1973 2/8 20/100
第五周 849/2822 2/10 20/120
第六周 962/ 3784 2/12 30/150
第七周 1883/5668 3/15 50/200
第八周 579/6247 1/16 30/230
第九周 1195/7442 3/19 30/260
posted @ 2019-11-16 21:02  冷冲  阅读(205)  评论(1编辑  收藏  举报