爱吃的LC

20172306 2018-2019-2 《Java程序设计与数据结构》第六周学习总结

20172306 2018-2019-2 《Java程序设计与数据结构》第六周学习总结

教材学习内容总结

  • 概述(了解一下树的一些概念)

    • 树是一种非线性结构。树由一个包含结点和边的集构成,其中的元素被存储在这些结点中,边则将一个结点和另一个结点连接起来。
    • 树的根就是位于该树顶层的唯一结点。一棵树只有一个结点。位于树中较低层的结点是上一层结点的孩子。一个结点只有一个双亲,但是可有多个孩子。
    • 根结点是树中唯一一个没有双亲的结点。没有任何孩子的结点为叶子。一个至少有一个孩子的非根结点为一个内部结点。
    • 根是树中所有结点的最终祖先,沿着起始自某一特定结点的路径可以到达的结点是该结点的子孙。
    • 通过计算从根到该结点所必须越过的边数目,可确定路径长度。树的高度是指从根到叶子之间最远路径的长度。
      对于以上的内容我画了一个图:
  • 树的分类:

    • 一种是树中任一结点可以具有的最大孩子数目。这个值有时称为该树的度。所含孩子无限为广义树;每个结点限制为不超过n个孩子的树称为n元树。最多两个孩子的叫二叉树。

    • 另一种是该树平衡与否。如果树的所有叶子都位于同一层或至少是彼此相差不超过一个层,就称之为平衡的。

    • 完全树是如果某树是平衡的,且底层所有叶子都位于树的左边,则是完全的

    • 满树是如果一棵n元树的所有叶子都位于同一层且每一结点要么是一片叶子要么正好具有n个孩子,则称树是满的。

  • 实现树的策略

    • 树的数组实现之计算策略

    • 我觉得这部分把握的重点是:对于任何存储在数组位置n处的元素而言,该元素的左孩子将存储在位置2n+1处,右孩子将存储在位置2(n+1)处。一般我们会将根结点放在索引0处,比较方便。但是通过看书发现这个有缺陷,因为如果其中一层缺少左或者右孩子,这样就会出现没有用的存储空间,而这部分空间是浪费掉的。

    • 一般而言,一棵含有m个元素的平衡n元树具有的高度为logn m。随着n增加,树的效率会越来越好。原因是因为,n变多,线性结构的最坏的情况所需的时间会越多,但是就树而言,即使在最坏的情况下,查找一条从根到叶子的路径,该路径不会长于logn m。

  • 树的遍历

    • 前序遍历:从根结点开始,访问每一结点及其孩子。
Visit node;
Traverse(left child)
Traverse(right child)
  • 中序遍历:从根结点开始,访问结点的左孩子,然后是该结点,再然后是任何剩余结点。
Traverse(left child)
Visit node;
Traverse(right child)
  • 后序遍历:从根结点开始,访问结点的孩子,然后是该结点。
Traverse(left child)
Traverse(right child)
Visit node;
  • 层序遍历:从根结点开始,访问每一层的所有结点,一次一层。

  • 注:实际的编译代码有两种情况,一种是利用递归,一种是利用循环,但是可以看到,我们利用递归更简单,而且想起来并不复杂,就把树拆分为每棵小树。递归方便。

  • 二叉树

    • 在二叉树中,我们可以看到书中有一个表格,中间放着可用的一些操作。我们可以和之前学习的线性结构进行对比,会发现,其中都是我们在线性结构中会出现的操作。
    • 为什么说没有添加和删除元素呢?因为每个元素和很多其他元素都相关联,因此对于一个元素的改变,对于其他元素都会有影响,那么我们该怎么处理这个影响呢,这个是需要很多其他信息的,因此,暂时没有删除和添加的操作。
  • 使用二叉树

    • 书中说利用二叉树进行后缀的计算。我觉得这很神奇啊,以前没学的时候还真没想到这一点,将符号和数字都存储到结点,然后利用递归进行一次又一次的操作。这和利用两个数组,一个放数字一个放符号然后进行进栈出栈的操作相比,简单了许多,负责多为O(1)。
    • 决策树:是这样的一种树,其结点表示决策点,其子结点表示在该决策点的可选项。对于问题,左子结点表示“否”,右子结点表示“是”。其实通俗来说,就是当我问一个问题时,这个问题就是根结点,然后它的左孩子就是根结点问题为否时,要问的问题,而它的右孩子就是根结点问题为是时,要问的问题。同理都是这样。

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

  • 问题1:在书中的那个树的数组实现之模拟链接策略这部分,我没有看懂,包括图我也就是大致懂,但是究其缘由,我还是不知道怎么回事?

  • 问题1解决方案:后来老师讲了这方面的知识,我才懂得书中的图到底说的是什么意思。
    不仅如此,老师还讲了孩子表达法、双亲孩子表达法、孩子兄弟表达法(二叉链表)等,都是很好的可以利用链表来模拟树的。

  • 问题2:书中主要学习了二叉树,所以我就更多的了解一下二叉树。

  • 问题2解决方案:我在网上主要查了一下有关二叉树的内容,发现这里所介绍的二叉树很详细而且通俗易懂,所以我就不总结啦,而且老师讲的有关二叉树的内容很详细,包括每个式子的推导方法。(性质1:在二叉树的第i层最多有2 (i-1) 个结点;性质2:深度为k的二叉树最多有2k-1个结点;性质3:对任何一棵二叉树,如果其叶结点个数为n0,度为2的结点数为n2,则有:n0=n2+1)

  • 问题3:在ExpressionTree中的printTree方法,我看不懂,我不知道这个代码是怎么回事?

  • 问题3解决方案:我一开始只是抱着看看其他人博客的心态看了看博客,看到2302的博客,发现他的问题和我的一样。我就开始就他写的基础上,开始理解这个到底怎么回事。后来又问了问2314,我们问题都遇到这类问题了

 public String printTree() {
        UnorderedListADT<BinaryTreeNode<T>> nodes = new ArrayUnorderedList<BinaryTreeNode<T>>();
        UnorderedListADT<Integer> levelList = new ArrayUnorderedList<Integer>();

        BinaryTreeNode<T> current;
        String result = "";
        int printDepth = this.getHeight();//树的高度
        int possibleNodes = (int) Math.pow(2, printDepth + 1);//根节点位置是0,最下层是第printDepth+1层,这个二叉树可能的总结点数就是2的printDepth+1次方
        int countNodes = 0;//结点数目

        nodes.addToRear(root);//在无序列表中添加根部结点
        Integer currentLevel = 0;//当前层
        Integer previousLevel = -1;//前一层
        levelList.addToRear(currentLevel);//把当前层添加到层数链表中

        while (countNodes < possibleNodes) {//此树不满时
            countNodes = countNodes + 1;//从0开始加
            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++);//第n层有2^(n-1)个数
                    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);//当前结点为空。往里加了null进去
                levelList.addToRear(currentLevel + 1);//增加层数
                result = result + " ";
            }
        }
        return result;
    }

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

  • 问题1:在运行PostfixTester时,没有出现应该出现的树,数字也没了,不知道为什么?

  • 问题1解决方案:我当然是进行了调试,然后就不断地找究竟问题出在了哪,后来发现在是getHeight没有编写,一开始我以为只要把代码从书中放进IDEA就可以了,有些方法还要自己编译,然后就成功了

  • 问题2:在进行诊断器的测试中,出现了No line found这个问题。

  • 问题2解决方案:因为在网上查Scanner太多会导致系统分不清,在System.in其中一个结束,所有的就都结束了,这个代码后面还有几个scanner的引用,所以将这个注释掉,让scanner不重复了,所以就好了。

代码托管

上周考试错题总结

  • 错题分析:无序列表的元素按客户选择的任何顺序保存。
  • 错题分析:这个我看过书后,在书中120页,写着,Java集合API中含有索引列表的三种实现。

结对及互评

点评模板:

  • 博客中值得学习的或问题:
    • 总结内容比较详细

点评过的同学博客和代码

  • 本周结对学习情况
    • 20172325
    • 结对学习内容
      • 一起学了第十章的内容,写了总结
      • 一起尝试编程第十章作业

其他(感悟、思考等,可选)

   第十章是非线性数据结构,是一个新的开始,但是又和之前的线性结构相联系,但是书中有很多代码我都还是不是很懂,即使知道内在的顺序,但是具体的代码我还是稀里糊涂,只能找同学问,所以,还是要继续学习啊!!!不过一开始看不懂想不通的地方,老师讲过之后就懂不少,而且我觉得老师的PPT挺有用的。里面的知识点很全。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 0/0 1/1 6/6
第二周 985/985 1/1 18/24
第三周 663/1648 1/1 16/40
第四周 1742 /3390 2/2 44/84
第五周 933/4323 1/1 23/107
第六周 1110/5433 2/2 44/151

参考资料

posted on 2018-10-25 22:05  爱吃的LC  阅读(337)  评论(2编辑  收藏  举报

导航