目录
学号20182323 2019-2020-1 《数据结构与面向对象程序设计》第9周学习总结
教材学习内容总结
第16章
树
-
树:树是一种非线性结构,其元素被组织成了一个层次结构。下面是树的术语,了解一下吧!
- 树有一个包含结点和边的集构成,其中的元素被储存在这些结点中,边则将一个结点和另一个结点连接起来。
- 根 :位于该树顶层上的唯一结点。一棵树只有一个根节点。
- 孩子 :位于树中较低层的结点是上一层结点的孩子。
- 兄弟 :同一双亲的多个孩子互称为兄弟。其一定位于同一层级上。
- 叶子 :没有任何孩子的结点称为孩子。
- 内部结点 :一个至少有一个孩子的非根节点称为一个内部结点。
- 根是树中所有结点的最终祖先(ancestor),沿着起始自某一特定结点的路径可以到达的结点是该结点的子孙(descendant)。
- 路径长度 :结点的层也就是从根结点到该结点的路径长度。
- 高度 :是指从根到叶子之间最远路径的长度。
-
树的分类:对树进行分类最重要的一条标准是++按度分类++,另一种方式是看该树++平衡与否++。
-
度即为树中任一结点可以具有的最大孩子数目。对结点所含有的孩子无限制的树称为广义树,每一结点限制不超过n个孩子的树称为n元树,而进行二胎政策的也就是结点最多有两个孩子的树称为二叉树。
-
对树进行分类的另一种方式是该树平衡与否。如果树的所有叶子都位于同一层或者至少是彼此相差不超过一个层,就称之为平衡的。
-
完全树:如果某树是平衡的,且底层所有叶子都位于树的左边,则认为该树是完全的。
- 完全二叉树是:在每个k层上都具有2的k次方个结点,最后一层除外,在最后一层必须是最左边结点。
-
满树:如果一颗n元树的所有叶子都位于同一层且每一结点要么是一片叶子要么正好具有n个孩子,则称此树是满的。
-
-
树的遍历
- 前序遍历(NLR——Preorder Traversal)也叫先序遍历,访问根节点的操作发生在遍历其左右子树之前。
- 中序遍历(LNR——Inorder Traversal),访问根节点的操作发生在遍历其左右子树之间。
- 后序遍历(LRN——Postorder Traversal),访问根节点的操作发生在遍历其左右子树之后。
下面的三个方法对应树的三种遍历方式:
// 前序遍历
let preOrderTraverseNode = function (node, callback) {
if (node !== null) {
callback(node.element);
preOrderTraverseNode(node.prev, callback);
preOrderTraverseNode(node.next, callback);
}
};
// 中序遍历
let inOrderTraverseNode = function (node, callback) {
if (node !== null) {
inOrderTraverseNode(node.prev, callback);
callback(node.element);
inOrderTraverseNode(node.next, callback);
}
};
// 后序遍历
let postOrderTraverseNode = function (node, callback) {
if (node !== null) {
postOrderTraverseNode(node.prev, callback);
postOrderTraverseNode(node.next, callback);
callback(node.element);
}
};
二叉树
- 二叉树的性质:若二叉树的根结点位于第一层
- 性质1:在二叉树的第i层最多有2^(i-1)个结点(i>=1)
- 性质二:深度为K的二叉树最多有2^K-1个结点(K>=1)
- 性质三:对任何一棵二叉树,如果其叶结点个数为n0,度为2的结点数为n2,则有:
n0 = n2 + 1
- 具有n个结点的完全二叉树的高度为[log2n]+1
第17章
-
二叉查找树:二叉树定义的扩展,一种带有附加属性的二叉树。附加属性是什么?++树中的每个节点,其左孩子都要小于其父节点,而父节点又小于或等于其右孩子。++
-
插入元素:
-
(1)不允许插入相同关键字,若二叉查找树中存在该关键字,则不插入
-
(2)我们可以先检索二叉树,看查找树中是否含有该关键字,若不存在,再做一次扫描将结点插入到适当位置。使用这种方式,为插入一个该关键字,做了两次扫描。
-
(3)注意到,插入的结点总是作为某一叶子节点的子结点,我们可以在第一次扫描过程中就确定待插入的位置,即把查找是否存在该关键字和查找可能的插入点在一次扫描中完成,提高插入效率。
-
-
删除元素:
在二叉查找树中删除一个给定的结点p有三种情况:
-
(1)结点p无左右子树,则直接删除该结点
-
(2)结点p有左子树(右子树),则把p的左子树(右子树)接到p的父节点上
-
(3)左右子树同时存在,找到结点p的中序直接后继结点s,把结点s的数据转移到结点p,然后删除结点s,由于结点s为p的右子树总最左的结点,因而s无左子树,删除结点s.
-
-
平衡二叉查找树:
-
引入:为什么平衡假设很重要?如果树不平衡,我们的分析会出现什么情况?
-
如果我们的树不平衡,那么得到的二叉树其实是一棵蜕化树,看起来像链表,并且比链表的效率还低,因为每个结点都附带多于的开销。addElement操作的复杂性为O(n)。而且蜕化树要浪费空间来存放那些未用的引用,并且很多算法会在沿着蜕化路径前进之前检查null引用。
-
那么该如何解决这个问题呢?
-
我们的目标是保持树的最大路径长度为log2(n)。解决的办法就是要有一个称为平衡的附加结构条件即:任何结点的深度不得过深。
-
平衡二叉树的定义:一棵平衡二叉树是其每个结点的左子树和右子树的高度最多相差1的二叉查找树(空树的高度为-1),这个差值也称为平衡因子(本书定义的平衡因子:右子树的高度减去左子树的高度),当平衡因子大于1或者小于-1的时候以该结点为树根的子树需要重新平衡。
-
-
平衡化技术通用方法:
- 左旋和右旋
- 将根结点的左孩子/右孩子(与不平衡的子树相反的一方)成为新的根结点,然后使原树根的左孩子的右孩子(右孩子的左孩子)成为原树根的新的右孩子(左孩子)
- 右左旋和左右旋
- 让树根右/左孩子的左/右孩子绕着树根的右/左孩子进行一次右/左旋。然后再让所得的树根右/左孩子绕着树根进行一次左/右旋
- 左旋和右旋
教材学习中的问题和解决过程
-
问题1:高度和深度究竟有什么区别?
-
问题1解决方案:
-
高度和深度一组相反的概念
-
高度是指当前结点到叶子结点的最长路径,如所有叶子结点的高度都为0。
-
深度则是指从根结点到当前结点的最大路径长度,如根结点的深度为0。
-
-
高度就是从要计算的结点开始寻找最远路径长度,深度就是从根结点到该结点的最大路径长度;在一棵树中,高度+深度 = 树中最远的路径长度。
代码调试中的问题和解决过程
-
问题1:不知道如何实现linkedBinaryTree中的toString方法,不知道如何输出这棵树.
-
解决过程:首先想用迭代器接解决,但是层序遍历调用的不是很正确,并且如何适当的把每一层分割开来,做出树的样子,这让我很苦恼。其实暂时还没解决。
-
问题2:当时在写hight时,理解错误了,当时写的是while循环,一直在循环去找左子树,然后只计算了层数。
-
解决过程:应该去递归找最远的路径,这样来讲我们应该递归去找每一条线路,然后通过比较找到最长的路径返回。
上周错题
-
1.The Java Collections API contains _________ implementations of an indexed list.
A.Two
B.Three
C.Four
D.Five
-
正确解答:因为列表可以分为有序列表、无序列表和索引列表
-
2.In removing an element from a binary search tree, another node must be ___________ to replace the node being removed.
A.duplicated
B.demoted
C.promoted
D .None of the
-
正确解答:当在二叉查找树上删除一个结点时,后面的结点需要向上移动来补全。当时,以为越靠近根结点说明深度越低,所以是降级了;但是看完答案好像人家的意思是向上补全。
代码托管
结对及互评
点评模板:
-
博客中值得学习的或问题:
- 随着学习内容难度增加,问题分析更加深刻
- 不断查阅资料,努力解决出现的问题
-
代码中值得学习的或问题:
- 代码的逻辑性有待提高
- 代码中适当加入注释会更好
-
基于评分标准,我给本博客打分:12分。得分情况如下:
-
正确使用Markdown语法(加1分):
- 不使用Markdown不加分
- 有语法错误的不加分(链接打不开,表格不对,列表不正确...)
- 排版混乱的不加分
-
模板中的要素齐全(加1分)
- 缺少“教材学习中的问题和解决过程”的不加分
- 缺少“代码调试中的问题和解决过程”的不加分
- 代码托管不能打开的不加分
- 缺少“结对及互评”的不能打开的不加分
- 缺少“上周考试错题总结”的不能加分
- 缺少“进度条”的不能加分
- 缺少“参考资料”的不能加分
-
教材学习中的问题和解决过程(2分)
-
代码调试中的问题和解决过程(2分)
-
本周有效代码超过300分行的(加0分)
-
其他加分:
- 周五前发博客的加1分
- 感想,体会不假大空的加1分
- 进度条中记录学习时间与改进情况的加1分
- 有动手写新代码的加1分
- 错题学习深入的加1分
- 点评认真,能指出博客和代码中的问题的加1分
- 结对学习情况真实可信的加1分
点评过的同学博客和代码
- 本周结对学习情况
- 结对同学学号20182315
- 结对照片
- 结对学习内容
- 树和二叉查找树
其他(感悟、思考等,可选)
继续潜心学习,只问初心,无问西东。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 10000行 | 30篇 | 400小时 | |
第一周 | 77/77 | 2/2 | 15/15 | |
第三周 | 424/501 | 3/5 | 30/30 | |
第四周 | 393/894 | 2/7 | 30/30 | |
第五周 | 320/1214 | 1/8 | 30/30 | |
第六周 | 904/2118 | 2/10 | 30/30 | |
第7周 | 1350/3468 | 3/13 | 30/30 | |
第8周 | 342/3810 | 1/14 | 30/30 | |
第9周 | 6048/9858 | 4/18 | 30/30 |
-
计划学习时间:25小时
-
实际学习时间:20小时
-
改进情况: