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

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

教材学习内容总结

本周学习了第10章

  • 10.1概述

    • 树是一种非线性结构,有一个包含结点和边的集构成。元素保存在结点中,边则将结点连接起来。
    • 一些术语

      根结点是位于树顶层的唯一结点
      位于树中较低层的结点是上一层结点的孩子,一个结点只有一个双亲
      同一双亲的两个结点称为兄弟
      根结点是树中唯一没有双亲的结点,没有任何孩子的结点称为叶子,其余为内部结点
      结点的层是从根结点到该结点的路径长度
      树的高度是指从根到叶子之间最远路径的长度

    • 树中任一结点可以具有的最大孩子数目称为该树的度。如果度没有限制,就称为广义树,每一结点孩子数不超过n个的树称为n元树。度为2的树称为二叉树。
    • 如果某树是平衡的(树的所有叶子都位于同一层或至少是彼此相差不超过一个层)且底层所有叶子都位于树的左边,则认为该树是完全树。
    • 如果一颗n元树的所有叶子都位于同一层且每一结点要么是一片叶子要么正好有n个孩子,则称此树是满的
  • 10.2实现树的策略
    • 计算策略:将元素n的左孩子置于位置(2xn - 1),将右孩子置于位置(2x(n + 1))。缺点是浪费大量存储空间。
    • 模拟链接策略:数组的每一元素都是一个结点类,每一结点存储的是每一孩子的数组索引。该策略允许连续分配数组位置而不用考虑树的完全性。
    • 一般而言,一棵含有m个元素的平衡n元树具有的高度为lognm
  • 10.3树的遍历
    • 前序遍历:从根结点开始,访问每一结点及其孩子
    • 中序遍历:根结点-->左边孩子-->结点-->剩余结点
    • 后序遍历:根结点-->孩子-->结点
    • 层序遍历:从根结点开始,访问每一层的所有结点,一次一层
  • 10.4二叉树
操作 说明
getRoot 返回指向二叉树根的引用
isEmpty 判定该树是否为空
size 判定树中的元素数目
contains 判定指定目标是否在该树中
find 如果找到指定元素,返回指向其的引用
toString 返回树的字符串表示
iteratorInOrder 为树的中序遍历返回一个迭代器
iteratorPreOrder 为树的前序遍历返回一个迭代器
iteratorPostOrder 为树的后序遍历返回一个迭代器
iteratorLevelOrder 为树的层序遍历返回一个迭代器

在所有列举的操作中 ,不存在往树中添加元素的操作。在一些树中也没有删除树元素的操作

  • 10.5使用二叉树:表达式树

    • 对表达式树的求值是从下往上的
  • 10.6背部疼痛诊断器
    • 决策树:其结点表示决策点,其子结点表示该决策点的候选项
    • 比较形象的一个决策树(有点偏差在于这一节里讲的都是二叉决策树)
  • 10.7用链表实现二叉树
    • 方法以递归式编写的时候,它们通常需要一个私有支持方法,因为第一个调用和随后每个用的签名和行为可能是不相同的

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

  • 问题1:程序列表10.3中判断是否是运算符的方法
public boolean isOperator(){
    return (termType == 1);
}

为什么需要判断termType为一时就是运算符

  • 问题1解决方案:参考前面的ExpressionOp的定义,设置了两个int变量和一个char变量
private int termType;
private char operator;
private int value;

结点存储只需要一个int变量存储操作数,一个char变量存储运算符。多出来的int变量termType说明就不是用于存储操作数。在这个类中,我发现termType的用处都是用来判断是否为操作数的,所以设置这个变量的意义就应该在于事先在设置结点时,就标明这个结点存储的是什么东西,如果是运算符就把termType改为1,不是就设为其他数,这样就避免了在判断时要写一长串的判断条件if (operator == "+" || operator == "-" || operator == "*" || operator == "/")的情况


  • 问题2:程序列表10.2ExpressionTree类提供了一个输出树的方法,不容易理解且输出是有问题的。
  • 问题2解决方案:结合具体代码进行分析
public String printTree() {
        UnorderedListADT<BinaryTreeNode<ExpressionTreeOp>> nodes = new ArrayUnorderedList<BinaryTreeNode<ExpressionTreeOp>>();//创建了一个存储BinaryTreeNode类的无序列表
        UnorderedListADT<Integer> levelList = new ArrayUnorderedList<Integer>();//创建一个存储int变量的无序列表

        BinaryTreeNode<ExpressionTreeOp> current;//设置指向无序列表的一个临时变量current
        String result = "";
        int printDepth = this.getHeight();//定义printDepth表示树的高度
        int possibleNodes = (int) Math.pow(2, printDepth + 1);//定义possibleNodes表示可能的树的结点数量多少,possibleNodes = 2 ^ (printDepth + 1)
        int countNodes = 0;

        nodes.addToRear(root);//把根结点添加到无序列表末尾
        Integer currentLevel = 0;
        Integer previousLevel = -1;//设置两个int变量,为接下来的换行操作进行判断
        levelList.addToRear(currentLevel);//currentLevel添加到levelList末尾

        while (countNodes < possibleNodes) {
            countNodes = countNodes + 1;
            current = nodes.removeFirst();//current为nodes移除的首位
            currentLevel = levelList.removeFirst();
            if (currentLevel > previousLevel) {
                result = result + "\n\n";//如果curreLevel大于previousLevel,就进行换行操作
                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();//将当前树的根结点加到result串中
                nodes.addToRear(current.getLeft());
                levelList.addToRear(currentLevel + 1);
                nodes.addToRear(current.getRight());
                levelList.addToRear(currentLevel + 1);//将前一个根结点的左右孩子都存入nodes的尾部,curreLevel+1存入levelList表示左右孩子是在根结点的下一行
            } else {
                nodes.addToRear(null);
                levelList.addToRear(currentLevel + 1);
                nodes.addToRear(null);
                levelList.addToRear(currentLevel + 1);
                result = result + " ";
            }

        }

        return result;
    }

我觉得这部分代码难理解的地方在于为了输出时的图像接近于我们一般的树的结构图而进行的换行操作和添加空格的操作。
判断某个结点在第几层时运用了一个levelList的一个列表,以及两个int变量currentLevel和previousLevel分别赋值为0和-1,通过currentLevel和previousLevel的关系判断是否需要换行,例如循环到第二层时,nodes里有了左右孩子两个结点,levelList里首位和第二位此时存储的都是1,而previousLevel此时为0,首先循环时currentLevel = levelList.removeFirst,currentLevel=1>previousLevel=0,所以需要另起一行result = result + "\n\n",之后将previousLevel赋为当前的currentLevel的值previousLevel = currentLevel;,current此时为nodes首位即左孩子,加入result字符串,再将左孩子的左右孩子分别加入列表尾,它们对应的levelList里的值为currentLevel+1=2,之后将列表头右孩子赋给current,此时的currLevel=previousLevel=1,所以走else这条路,不需要换行然后进行接下来的操作,如果右孩子为叶结点,虽然没有子结点,但是依然会留有存储空间nodes.addToRear(current.getLeft());,只不过里面存放的是null,所以输出时计算机走到此处会继续执行,并不断创建新的存储空间。所以在外面需要套一层while循环,因为二叉树前n层有不高于2^(n+1)个元素,所以定义possibleNodes的值为int possibleNodes = (int) Math.pow(2, printDepth + 1);
另外关于加空格的方法不是太懂,譬如为何要这么定义j < ((Math.pow(2, (printDepth - currentLevel))) - 1)在两个结点之间添加空格。
关于两者的取值好像也不是那么严格,也就是不一定非要取0和-1,换成1和0,-1和-2之类也是可以的,只不过取值的不同会影响树结构的宽窄,或者两者的差值也不一定需要为1,差2差3好像都没有问题,只不过后面levelList.addToRear(currentLevel + 1);的方法,对应就该加2或者加3了。

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

  • 问题1:运行expressionTree类的printTree方法时,树的结构没有全部打印出来,如图
  • 问题1解决方案:debug一下,发现我还没有完成getHeight方法,getHeight方法那儿还是return 0;自然表示上会出错。返回height的方法我想应该分作三步,即判断树的结点分别是根结点、内部结点以及叶结点,首先判断根结点是否为空,不为空高度加一,之后用一个while循环以及PP10.3的方法反复判断接下的结点是否为内部结点,若是则高度加一,结点赋为该结点的左孩子,若判断出该结点为叶结点,则高度加一再返回高度值。
BinaryTreeNode cur = root;
        int height = 0;
        if (root != null){
            height++;
        }
        cur = cur.left;
        while (cur.judge() != true){
            height++;
            cur = cur.left;
        }
        height++;
        return height;

代码修改后的运行截图为


  • 问题2:使用LinkedBinaryTree的toString方法时最终输出一串乱码
  • 问题2解决方案:在网上寻找解决方案,然后了解到数组是没有toString方法的。

    Object中的toString()方法,是将传入的参数的类型名和摘要(字符串的hashcode的十六进制编码)返回,直接对数组使用了toString()方法,就会得到 一个Ljava.lang.String;@175d6ab
    其中,Ljava.lang.String 是指数据是String类型的
    虽然这里给出的乱码信息是3ecf72fd,但是他给出的解决方案是使用循环的方法来输出数组中的每一个值,姑且一试
    这里输出树的结构需要用到递归,然后输出时有点奇怪的就是我把右孩子放在其双亲的上面,左孩子放在双亲的下面,所以会有些不像树的形状

public void oString() {
        string(root);
    }

private void string(BinaryTreeNode temp){
        if(temp != null){
            string(temp.getRight());
            System.out.println(temp.getElement() + " ");
            string(temp.getLeft());
        }
    }

输出结果如图

凑合也能看

代码托管

上周考试错题总结

上周没有错题哦

结对及互评

  • 博客中值得学习的或问题:

    • 谭鑫的博客一直保持很高的水准,特别是问题的总结和解决能力都值得学习,能看出来是在用心学习
    • 方艺雯的博客教材学习内容总结认真详细,并配有图示和自己的理解,点个赞
  • 基于评分标准,我给谭鑫的博客打分:8分。得分情况如下:
    正确使用Markdown语法(加1分):
    模板中的要素齐全(加1分)
    教材学习中的问题和解决过程, 三个问题加3分
    代码调试中的问题和解决过程, 三个问题加3分
  • 基于评分标准,我给方艺雯的博客打分:8分。得分情况如下:、
    正确使用Markdown语法(加1分):
    模板中的要素齐全(加1分)
    教材学习中的问题和解决过程, 两个问题加2分
    代码调试中的问题和解决过程, 三个问题加3分
    排版精美加1分
  • 本周结对学习情况
    • 20172305
    • 20172314
    • 结对学习内容
  • 上周博客互评情况

其他

本周的学习情况还算不错,最困难的地方不在于几个PP项目,反而在于问题中提到的那个printTree的代码的理解。不过在考试中发挥得有点糟糕,不知道怎么的错了两道不该错的题

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 0/0 1/1 8/8
第二周 470/470 1/2 12/20
第三周 685/1155 2/4 10/30
第四周 2499/3654 2/6 12/42
第六周 1218/4872 2/8 10/52
第七周 590/5462 1/9 12/64

参考资料

原文地址:https://www.cnblogs.com/Lewandodoski/p/9843171.html

时间: 2024-10-08 13:52:08

20172323 2018-2019-1 《程序设计与数据结构》第六周学习总结的相关文章

20172323 2018-2019-1 《程序设计与数据结构》第一周学习总结

20172323 2018-2019-1 <程序设计与数据结构>第一周学习总结 教材学习内容总结 第一章--概述 1.1 软件质量 软件工程(Software Engineering)是一门关于高质量软件开发的技术和理论的学科. 解决的问题:控制开发过程,实现高质量的软件 软件工程的目标 高质量软件的特征 1.2 数据结构 数据结构:计算机存储.组织数据的形式. 程序 = 数据结构 + 算法 软件 = 程序 + 软件工程 栈会颠倒数据的顺序,而队列可以保持数据的顺序. 第二章--算法分析 算法

20172305 2017-2018-2 《程序设计与数据结构》第一周学习总结

20172305 2017-2018-2 <程序设计与数据结构>第一周学习总结 教材学习内容总结 本书的第一章简单的介绍了计算机和JAVA的历史,基础内容很多,代码的讲解还没用正式进入,本周一直在做敲代码的准备,简单敲了老师给的"Hello World!"以及书后的PP1.3.PP1.4等简单的小程序. 教材学习中的问题和解决过程 问题1:三种不同类型的错误,运行错误和逻辑错误的混淆 问题1解决方案:针对EX1.20的"希望做加法时却做里乘法"进行了网上

20172314 2017-2018-2 《程序设计与数据结构》第一周学习总结

20172314 2017-2018-2 <程序设计与数据结构>第一周学习总结 教材学习内容总结 本书第一章为计算机系统概述,前面是一些计算机相关的基础知识,让我对计算机有了一个总体的认识,不再是一片空白了,对主存储器和CPU影响深刻,主存储器用于保存程序和数据,CPU执行程序指令.在接下来的Java编程语言与程序开发部分,开始看的时候有点迷茫,不是很理解,后来先按照作业中附带的流程完成一些代码托管之后,接触了完整的简单的程序之后,再回过头来看书,看到的一些陌生的名词在脑海中就有了实际的对应,

20172317《程序设计与数据结构》第一周学习总结

20172317 2017-2018-2 <程序设计与数据结构>第一周学习总结 教材学习内容总结 重新温习了一遍计算机的基础 总算了解了局域网广域网因特网万维网这些东西之间的区别了 通过URL的例子知道了网址各个部分的含义 对Java编程语言和程序开发有了一个粗浅的了解 教材学习中的问题和解决过程 问题:练习题SR1.13出现了答案与题目不相符的情况 问题解决方案:题中有个选项是"网卡",答案中没有,反而有个题目没有的选项"调制解调器"(俗称"

20172322 2017-2018-2 《程序设计与数据结构》第二周学习总结

20172322 2017-2018-2 <程序设计与数据结构>第二周学习总结 教材学习内容总结 了解了print与println的区别 了解了字符串的拼接可以用+来完成 了解了转义字符的使用 学会了使用赋值 学会使用部分算术运算符 学会了使用Scanner来实现交互性 教材学习中的问题和解决过程 问题1:在最初接触赋值时对foalt和double的赋值范围不了解 问题1解决方案:使用万能的度娘后看到一个高赞答案后有了了解 问题2:在提前预习时看到2.7图形后敲入的代码无法执行 问题2解决方案

20172328《程序设计与数据结构》第二周学习总结

20172328李馨雨<程序设计与数据结构>第二周学习总结 又到周五,李馨雨同学要开始写博客了.让我们开始吧!(????) 教材学习内容总结 1.首先是String类定义的字符串,然后是print和println的区别.转义字符的学习.(让我印象深刻的\b[回车符]在字符串结尾不显示哈哈,及其更新的\t[换行符],还有在课堂上真正明白了什么是回车.) 2.了解变量.常量.赋值语句.变量:保存数据的内存单元.常量:坚定自己不会变的数据!除非你用java的反射(有点复杂,改权限.去修饰符等等.没实

20172327 2017-2018-2 《程序设计与数据结构》第二周学习总结

20172327 2017-2018-2 <程序设计与数据结构>第二周学习总结 教材学习内容总结 字符串的拼接和转义序列的使用 变量的声明和使用 讨论语法及表达式的处理 定义数据转换类型和实现类型转换的机制 创建Scanner类 教材学习中的问题和解决问题 暂无 代码学习中的问题和解决过程 问题1:在提交过程中,突然遇到无法上传的情况 问题2解决方案:通过上网查找,输入git pull之后弹出一个编辑框,选择关闭之后,再次用git push就成功了. 问题2:在按照例题2.10打代码时,Jav

学号20172328《程序设计与数据结构》第九周学习总结

学号20172328<程序设计与数据结构>第九周学习总结 教材学习内容总结(异常和递归) 第11章:异常 1.[异常处理]: 一个异常:是一个定义非正式情况或错误的对象,由程序或者运行时环境抛出,可以根据需要捕获和处理. 错误:错误类似于异常,但是错误代表不可恢复的问题并且必须捕获处理. 2.[处理异常的三种方法]:①根本不处理异常②当异常发生时处理异常③在程序的某个位置集中处理异常. 3.[未捕获的异常]:如果程序中不处理异常,则程序将非正常的终止运行,并产生关于描述在何处发生什么异常的信息

20172326 《程序设计与数据结构》第九周学习总结

学号 20172326 <程序设计与数据结构>第九周学习总结 教材学习内容总结 异常(exception):定义非正常情况下或错误的情况的对象,由程序或运行时环境抛出,可根据需要进行相应的捕获处理. 异常与错误的区别:错误代表不可恢复的问题并且必须捕获处理.而异常可以忽视,或者使用try语句处理,或调用更高级的方法. 可检测异常与不可检测异常:可检测异常必须由方法捕获,或者必须在可能抛出或传递异常方法的throws子句中列出来.在方法定义的声明头中追加一条throws子句.不可检测异常不需要使

20172322 2017-2018-2 《程序设计与数据结构》第九周学习总结

20172322 2017-2018-2 <程序设计与数据结构>第九周学习总结 教材学习内容总结 异常 学会了使用try-catch来实现未捕获的异常的处理.可以使得异常被捕获进而不导致程序出现错误退出.使用try写入可能产生异常的语句,使用catch来编写在捕获异常后继续执行的代码(可以为空). "未捕获的异常"指在编译过程中不会被编译软件显示异常但是在运行时会出现异常导致程序直接退出,例如:"ArithmeticException"."In