20172305 2018-2019-1 《Java软件结构与数据结构》第六周学习总结
20172305 2018-2019-1 《Java软件结构与数据结构》第六周学习总结
教材学习内容总结
本周内容主要为书第十章内容:
- 树(一种非线性结构,其中的元素被组织成一个层次结构)
- 结点:树中的一个位置。
- 边:树中两个结点的连接。
- 根结点:就是指位于该树顶层的唯一结点。一棵树只有一个根结点,根结点没有父节点。
- 子结点:一个树中较低层的结点是上一层结点的子结点。位于树中当前结点下面的结点,并由边与之直接连接。
- 同胞结点:属于同一结点的子结点。
- 叶结点:没有任何子结点的结点。
- 内部节点:一个至少有一个子结点的非根节点。
- 祖先节点:位于当前结点以上的结点。
- 后代结点:位于当前结点一下的结点。
- 路径长度:通过计算从根到该结点所必须越过的边数目。
- 高度:从根到叶子之间的最远路径的长度。
- 阶(度):树中任一结点可以具有的最大子结点的数目。
- 树的分类:
- 二叉树:结点最多具有两个孩子的树。
- 完全树:如果某树是平衡的,且底层所有叶子都位于树的左边,则认为该树是完全的。
- 满树:如果一颗n元树的所有叶子都位于同一层且每一结点要么是一片叶子,要么是正好具有n个孩子。
- 完全二叉树:在每个K层上都有2^k个结点,最后一层除外,在最后一层中的结点必须是在最左边结点。/ 在每个k层上都具有2^k个结点,最后一层除外,在最后一层中的结点必须是最左的。
- 平衡树与非平衡树:
含有m个元素的平衡n元树具有的高度为lognm。
- 树的遍历:
- 前序遍历:从根结点开始,访问每一个结点及其孩子。(A->B->D->E->C)
- 中序遍历:从根结点开始,访问结点的左侧孩子,然后是该结点,再然后是任何剩余的结点。(D->B->E->A->C)
- 后序遍历:从根结点开始,访问结点的孩子,然后是该结点。(D->E->B->C->A)
- 层序遍历:从根节点开始,访问每一层的所有结点,一次一层。(A->B->C->D->E)
对于任何存储在数组位置n处的元素而言,该元素的左结点将存储在位置2n+1处,该元素的右结点将存储在位置2(n+1)处。
模拟链接策略允许连续分配数组位置而不用考虑该树的完全性。
二叉树--表达式树表达式树的及其内部结点包含着操作,且所有叶子也包含着操作数。对操作树的求值是从下往上的。
二叉树--决策树(背部疼痛诊断器)决策树的结点表示决策点,其子结点表示在该决策点的可选项。决策树的叶结点表示可能的判断,这些推断是根据决策结果得出的。
教材学习中的问题和解决过程
- 问题1:完全二叉树和满二叉树的区别?
- 问题1解决方案:满二叉树是完全二叉树的一种特殊。故满二叉树肯定是完全二叉树,完全二叉树不一定是满二叉树。是因为完全二叉树倒数第二层的结点可以有一个子结点(当然是左侧节点),可以有两个结点,也可以无子结点。而满二叉树则要最后一层的结点数必须为最大的,这就要求倒数第二层的每个结点其子结点必须是两个 即为满二叉树的倒数第二层的结点无叶结点的情况。
- 满二叉树是指除最后一层外,每一层上的所有结点都有两个子结点。
- 如果一颗满二叉树的深度为d,最大层数为k
- 它的叶子数是: 2^d
- 第k层的节点数是: 2^(k-1)
- 总节点数是: 2^k-1 =>
(1 + 2 + 4 + 8 ··· + 2^(k-1)的和)
,其总节点数一定是奇数。
- 完全二叉树是指除最后一层外,每一层上的结点数均达到最大值;在最后一层上只缺少右边的若干结点。
- 完全二叉树的判断方法:叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
- 完全二叉树的特点是:
- 只允许最后一层有空缺结点且空缺在右边,即叶子结点只能在层次最大的两层上出现。
- 对任一结点,如果其右子树的深度为j,则其左子树的深度必为j或j+1。 即度为1的点只有1个或0个。
- 问题2:书上表达式树printTree()代码如何理解?
- 问题2解决方案:PostfixEvaluator类的getTree()内容是
(treeStack.peek()).printTree()
是把树的形式从栈treeStack的顶部返回出来,再调用Expreesion类中的printTree方法(最恶心的部分),就成一棵树了。
public String printTree() {UnorderedListADT<BinaryTreeNode<ExpressionTreeOp>> nodes = new ArrayUnorderedList<BinaryTreeNode<ExpressionTreeOp>>();UnorderedListADT<Integer> levelList = new ArrayUnorderedList<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;}
- 代码中的两个无序列表,一个存放的是BinaryTreeNode类型,就是表达式树的每一个结点;另一个存放的是Integer类型,用来与之前的无序列表对应,每往无序列表中存放一个结点,就在另一个无序列表中存入对应的层数。
- 代码中的几个整形变量,printDepth输出的是高度(从零开始的,实际树是四层就输出三层,根结点所在层数为0),possibleNode通过调用Math的静态方法pow()来算树的最大结点数。其中
Math.pow(2, printDepth + 1)
按照老师讲的应该是2^printDepth - 1
,但是算法给出的是2^(printDepth+1)
,实际上我们调用的getHeight()方法会从第零行开始计算,而在实际上是从一层开始的,这样的话就需要把再加1。而尾部的减1,没有再此体现。在后面的while循环的条件来看,记录输出结点数量的变量 < possibleNodes,这样的话就可以使得记录输出结点数量的变量最大情况等于possibleNodes - 1,这样就是最大结点数。还有三个整形变量,一个是countNodes,是记录输出的结点数目的;一个是currentLevel记录当前结点所在的层;一个是previousLevel记录的是当前结点的前一层。 过程:调出根结点A,此时对应的层数是-1,存放到对应的无序列表中。此时,countNodes(输出的结点数目)的初始值为0,
开始第一次进入循环,countNodes加1,调出无序列表中的结点。此时根结点的层数为0,前一层为-1,进入第一个条件,换行previousLevel等于currentLevel(两个变量值都为0),然后输出根节点的内容,跳出第一个条件。进入第二个条件,将根结点的左子结点添加到无序列表的尾部,对应的记录层数的无序列表添加数字1,再将根结点的右子结点添加到无序列表,对应记录层数的无序列表添加数字1,第一次循环结束。
进行第二次循环,此时调出根结点的左子结点的内容和左子结点的层数,层数为1,前一层是0,进入第一个条件,换行previousLevel等于currentLevel(两个变量值都为1),然后输出左子结点的内容,跳出第一个条件。进入第二个条件,往里面插入左结点的子结点,此时存放节点的无序列表内有和输出的左结点同一层的右结点,和左结点的两个子结点,先左节点后右结点,对应的层数应该均为3,第二次循环结束。
进行第三次循环,此时调出的是根结点的右子结点和层数,层数和左结点相同也为1,进入第一个条件(else部分),取消了换行和previousLevel等于currentLevel,这样的话就和左子结点同行输出,把根结点的两个子结点都输出来了。跳出第一个条件,再将右结点的两个子结点和对应的层数放到无序列表,其中两个子结点的层数均为2,第三次循环结束。
进行第四次循环,此时调出的根结点的左结点的左子结点,此时对应的层数是2。此时的previousLevel为1,currentLevel为2,进入第一个条件的if部分,进行换行并输出该结点的内容,跳出第一个条件,因为该结点为空,所以进入第二个条件的else部分,会默认添加该结点的两个子结点,但是子结点的内容为空,即插入到无序列表的内容为空,但是层数会进行增加,第四次循环结束。
重复进行上述循环(已经调用整个部分的相关代码,股不在叙述操作),最后达到循环超过该树的总结点数即possibleNodes跳出循环,输出result就是整个树了。- 问题3:背部疼痛诊断器的诊断过程总是回答完一个yes之后就蹦了?
问题3的解决方案:针对这个问题,刚开始只是敲上去而没有真正去运行。后来听同学的运行之后有问题,这才去运行,结果真有问题。不能转化为String,很神奇!!!明明在txt文件内已经有了内容的,就是转换不成String。刚开始以为是读文件的部分有问题,但是没找到问题,通过单步调试也只是在最后一步有问题。所以,很疑惑!更关键的是这个同样的代码在别的电脑上会有运行成功的。相同的一段代码,我的电脑上会提醒有个判断总是false,而别的上面就没有。很迷...通过侯泽洋的帮助,是我们在获得左结点或是右结点时候只是调出其中的内容,该节点的子结点根本没有调出来导致的,完全就是个只有该结点的一个树了,在LinkedBinaryTree中添加几句就可以结点的子结点都调出来了。
- 始终有问题的部分:
- 错误图片:
- 王文彬提供的代码(修改位置):
- 侯泽洋提供的代码(修改位置):
代码学习中的问题和解决过程
- 问题1:链表实现的二叉树的toSring代码如何编写?
问题1的解决方案:
return super.toString();
会出现带有包名的哈希码,没有正常的输出内容。准备重新书写的输出的代码的时候,发现如果输出的话就需要用递归的方法,来从树中一层一层的从左往右的按顺序输出。但是如果用到了递归的话,注定用String类型的变量输出不出来(因为要进行一个叠加的过程,而设置变量的话也不能在此方法下进行输出。需要像之前的那个归并排序和快速排序一样,一个进行递归的主要方法,另一个调用该递归方法,来达到代码的实现。)图过时用递归来实现的话,就可以运用不同的遍历方式。通过书上代码--表达式树的输出树状形式,就直接搬过来实现toString方法(相关代码分析在教材分析总结)。- 产生带包名哈希码:
- 前序输出:从根结点开始,访问每一个结点及其子结点。所以,先调出根结点的内容,然后从左结点开始调出至右结点的内容。
- 中序输出:从根结点开始,先访问结点的左子结点的内容,在调出该结点的内容,再访问结点的右子结点的内容。
- 后序输出:从根结点开始,先访问该结点的子结点的内容,在退回到结点的内容。
- 层序输出:从根节点开始,每一层的从左到右的进行输出。
- 树状输出(借鉴表达式树的形式):
- 问题2:表达式树的输出为什么总是输出不对?
问题2解决方案:书上表达式树的代码在进行树的输出时候,总会输出的稀乱稀乱的一堆,代码也没有爆红。第一次通过单步调试发现,是自己的getHeight()方法的方法体没有写,导致输出的结果总是0。还要自己修改getHeight()...
悲惨自行补了相关代码,先判断树是不是空的,不空的话通过PP10.3做的代码,进行判断是否是叶结点进行循环遍历,在遍历的过程中进行计数。但是在输出树的情况下就是缺最后一行,通过尝试对一个已知高度的树调用getHeight()方法时,在输出的时候发现会比实际高度少1,所以在计数变量的初始值从0改为1尝试一下,结果就完整了。- 第一次修改:
- 第二次修改:
- 第三次修改:
- 第一次修改:
- 问题3:removeRightSubtree、removeAllElement和contains方法
- 问题3解决方案:
- 针对removeRightSubtree方法觉得需要先进行遍历,每遍历一个再删除一个,直到完成任务。后来想想觉得好麻烦,还要进行迭代。想出一个简单粗暴的方法,就是已经确定删除右枝杈了,那么就直接把节点的右侧枝杈直接改为null就可以了,根本不用管其内容就是删。但是,做出的第一个版本,是删除根结点的右侧,那么如果想删除某个节点的右侧,这样的话方法就不会起作用。所以,改进了此方法以实现可以删除某一个节点的右子结点。
- 针对removeAllElement方法,因为实现前一个方法时简单粗暴,而此方法和之前的有一定的类似,所以直接就重新定义一个BinaryTreeNode类的根结点,让其为零,再使这个结点替代之前有内容的树就可以了。
- 针对contains方法,这个方法是判断指定目标是否在该树上。因为之前有书上的find方法作支撑,就通过该方法查找出是否有指定元素,如果就输出true,没有就false。
代码托管
上周考试错题总结
无错题,终于不用错题总结了...
结对与互评
点评(王禹涵)
- 博客中值得学习的或问题:
- 背景图很好看,但是截图内容看得不是很清晰。问题2的代码也进行了注释,是我应该学习的地方。
- 代码中值得学习的或问题:
- 代码图片也是看的不清晰,问题提的很好,问题2出现的是哈希码,建议可以尝试这用四种遍历顺序输出,或是像树那样输出。
- 基于评分标准,我给本博客打分:8分。
- 得分情况如下:
- 正确使用Markdown语法(加1分)
- 模板中的要素齐全(加1分)
- 教材学习中的问题和解决过程, 两个问题加2分
- 代码调试中的问题和解决过程, 两个问题加2分
- 感想,体会不假大空的加1分
- 点评认真,能指出博客和代码中的问题的加1分
点评(方艺雯)
- 博客中值得学习的或问题:
- 图片特别细致清晰,而且针对实现树的策略写的很详细,针对printTree方法可以更进一步的描述运算过程。
- 代码中值得学习的或问题:
- 代码问题记录详细,第二个问题我也遇到过。建议在插图的时候可以添加多一点的文字描述,没有什么大问题,写的很棒棒。
- 基于评分标准,我给本博客打分:10分。
- 得分情况如下:
- 正确使用Markdown语法(加1分)
- 模板中的要素齐全(加1分)
- 教材学习中的问题和解决过程, 二个问题加2分
- 代码调试中的问题和解决过程, 四个问题加4分
- 感想,体会不假大空的加1分
- 点评认真,能指出博客和代码中的问题的加1分
互评对象
本周结对学习情况
20172314方艺雯
20172323王禹涵结对学习内容:树
感悟
第十章的树学起来很费劲,完全的一个接着一个,没有顺序,没有结构的(二叉树还好点)。课后的代码相对简单,但是书上的示例代码写的比课后代码还麻烦。非常感谢侯泽洋的帮助,帮助我更好的理解树的相关知识,有些代码的问题是在帮助下完成的,这也显示出我的不足,没有更好的掌握知识,逻辑的相关内容只有自己弄懂才行,别人的帮助只是辅助的。起初还感觉前面代码相对简单,但那是到了树的部分真是欲哭无泪的感觉。只能再好好的学习学习再学习了。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/1 | 15/15 | |
第二周 | 703/703 | 1/2 | 20/35 | |
第三周 | 762/1465 | 1/3 | 20/55 | |
第四周 | 2073/3538 | 1/4 | 40/95 | |
第五周 | 981/4519 | 2/6 | 40/135 | |
第六周 | 1088/5607 | 2/8 | 50/185 |
参考资料
- 完全二叉树
- 满二叉树
转载于:https://www.cnblogs.com/sanjinge/p/9853110.html
20172305 2018-2019-1 《Java软件结构与数据结构》第六周学习总结相关推荐
- 2018-2019-20172329 《Java软件结构与数据结构》第九周学习总结
2018-2019-20172329 <Java软件结构与数据结构>第九周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十五章-图 一.图及无向图 1.图的相关概 ...
- 2018-2019-20172321 《Java软件结构与数据结构》第四周学习总结
2018-2019-20172321 <Java软件结构与数据结构>第四周学习总结 教材学习内容总结 第六章 6.1列表集合 列表集合是一种概念性表示法,其思想是使事物以线性列表的方式进行 ...
- 达拉草201771010105《面向对象程序设计(java)》第十六周学习总结
达拉草201771010105<面向对象程序设计(java)>第十六周学习总结 第一部分:理论知识 1.程序与进程的概念: (1)程序是一段静态的代码,它是应用程序执行的蓝 本. (2)进 ...
- 杨玲 201771010133《面向对象程序设计(java)》第十六周学习总结
<面向对象程序设计(java)>第十六周学习总结 第一部分:理论知识学习部分 1.程序是一段静态的代码,它是应用程序执行的蓝本.进程是程序的一次动态执行,它对应了从代码加载.执行至执行完毕 ...
- 201771010101 白玛次仁 《2018面向对象程序设计(Java)》第十六周学习总结
实验十六 线程技术 实验时间 2017-12-8 1.学习总结: 1.程序 是一段静态的代码,它应用程序执行蓝 是一段静态的代码,它应用程序执行蓝 本. 2.进程 是程序的一次动态执行,它对应了从代 ...
- 201771010137 赵栋《面向对象程序设计(java)》第十六周学习总结
1.实验目的与要求 (1) 掌握线程概念: (2) 掌握线程创建的两种技术: (3) 理解和掌握线程的优先级属性及调度方法: (4) 掌握线程同步的概念及实现技术: 2.实验内容和步骤 实验1:测试程 ...
- 201771010126 王燕《面向对象程序设计(Java)》第十六周学习总结
实验十六 线程技术 实验时间 2017-12-8 1.实验目的与要求 (1) 掌握线程概念: ‐多线程 是进程执行过中产生的多条线索. 是进程执行过中产生的多条线索. 是进程执行过中产生的多条线索. ...
- 201771010109焦旭超《面向对象程序设计(java)》第十六周学习总结
1.实验目的与要求 (1) 掌握线程概念: (2) 掌握线程创建的两种技术: (3) 理解和掌握线程的优先级属性及调度方法: (4) 掌握线程同步的概念及实现技术: 2.实验内容和步骤 实验1:测试程 ...
- 数据结构java 图实验代码_20172329 2018-2019 《Java软件结构与数据结构》实验三报告...
20172329 2018-2019-2 <Java软件结构与数据结构>实验三报告 课程:<Java软件结构与数据结构>html 班级: 1723java 姓名: 王文彬lin ...
最新文章
- [c#基础]关于try...catch最常见的笔试题
- Asp.net实现在线截图(大图截取为小图)
- halcon入门_visionpro和halcon这两款机器视觉软件区别
- 报告解读丨企服必看!如何高效搭建规模化营销获客体系?
- const char* p 、char* const p、const (char*) p 理解记忆
- 自适应网页设计(转)
- LeetCode刷题(25)
- Flask详解(中篇)
- 阶段3 2.Spring_05.基于XML的IOC的案例1_4 注解IOC案例-把自己编写的类使用注解配置...
- 解决办法:std没有成员initializer_list
- 【图像分割】基于matlab人工鱼群算法图像分割【含Matlab源码 1488期】
- [常用工具]深度学习Caffe处理工具
- ZohoCRM客户管理系统应用的案例分享
- 《关键对话——何谓关键对话》读书笔记(一)
- python搜索pdf内容所在页码_使用pyPDF从文档中检索页码
- AI绘图参数设置和一些注意点
- 前端数组如何传到后台
- python的开发者太负责任了_人生苦短,我用 Python
- 嵌入式系统设计电子书
- 燕十八 php经典,燕十八PHP传世经典第1部视频教程(后半部分)_PHP教程
热门文章
- 通过线上解决线下痛点来推广自己的小程序
- 微信小程序与H5标签、样式对比
- 【毕业设计】大数据公交数据分析与可视化 - 大数据 python falsk
- spring cloud实战(五)UAA
- 陈妍希和你一起带“蛙儿子”做公益,守护宝贝她有话跟你说!
- 【WhatsApp营销】如何使用WhatsApp动态(Status)吸引客户?
- pythonchallenge闯关游戏_PythonChallenge闯关详解
- 聊聊后端Web开发框架(Python)的简单使用
- 给Adobe Reader添加书签功能
- Excel学习日记:L15-If函数