20172328 2018-2019《Java软件结构与数据结构》第七周学习总结

20172328 2018-2019《Java软件结构与数据结构》第七周学习总结

概述 Generalization

本周学习了第11章:二叉查找树。在本章中,主要探讨了二叉查找树的概念和各种二叉查找树实现,考察为二叉查找树添加和删除元素的算法以及维护平衡二叉查找树的算法

教材学习内容总结 A summary of textbook

  • 二叉查找树(binary search tree):二叉树定义的扩展,一种带有附加属性的二叉树。附加属性是什么?树中的每个节点,其左孩子都要小于其父节点,而父节点又小于或等于其右孩子。
  • 插入元素(addElement)
    • (1)不允许插入相同关键字,若二叉查找树中存在该关键字,则不插入
    • (2)我们可以先检索二叉树,看查找树中是否含有该关键字,若不存在,再做一次扫描将结点插入到适当位置。使用这种方式,为插入一个该关键字,做了两次扫描。
    • (3)注意到,插入的结点总是作为某一叶子节点的子结点,我们可以在第一次扫描过程中就确定待插入的位置,即把查找是否存在该关键字和查找可能的插入点在一次扫描中完成,提高插入效率。
  • 删除元素(removeElement)
    在二叉查找树中删除一个给定的结点p有三种情况:

    • (1)结点p无左右子树,则直接删除该结点
    • (2)结点p有左子树(右子树),则把p的左子树(右子树)接到p的父节点上
    • (3)左右子树同时存在,找到结点p的中序直接后继结点s,把结点s的数据转移到结点p,然后删除结点s,由于结点s为p的右子树总最左的结点,因而s无左子树,删除结点s.
  • 平衡二叉查找树:
    • 引入:为什么平衡假设很重要?如果树不平衡,我们的分析会出现什么情况?
    • 如果我们的树不平衡,那么得到的二叉树其实是一棵蜕化树,看起来像链表,并且比链表的效率还低,因为每个结点都附带多于的开销。addElement操作的复杂性为O(n)。而且蜕化树要浪费空间来存放那些未用的引用,并且很多算法会在沿着蜕化路径前进之前检查null引用。
    • 那么该如何解决这个问题呢?
    • 我们的目标是保持树的最大路径长度为log2(n)。解决的办法就是要有一个称为平衡的附加结构条件即:任何结点的深度不得过深。
    • 平衡二叉树(Balanced Binary Tree)的定义:一棵平衡二叉树是其每个结点的左子树和右子树的高度最多相差1的二叉查找树(空树的高度为-1),这个差值也称为平衡因子(本书定义的平衡因子:右子树的高度减去左子树的高度),当平衡因子大于1或者小于-1的时候以该结点为树根的子树需要重新平衡。
    • AVL树只是实现平衡二叉树的一种方法,它还有很多的其他实现方法如红黑树、替罪羊树、Treap、伸展树等。
  • 平衡化技术通用方法:
    • 右旋:

      • 使树根的左孩子元素成为新的根元素。
      • 使原根元素成为这个新树根的右孩子元素
      • 使原树根的左孩子的右孩子,成为原树根的新的左孩子。
    • 左旋:
      • 使树根的右孩子元素成为新的根元素。
      • 使原根元素成为这个新树根的左孩子元素
      • 使原树根的右孩子的左孩子,成为原树根的新的右孩子。
    • 右左旋:
      • 让树根右孩子的左孩子绕着树根的右孩子进行一次右旋。
      • 然后再让所得的树根右孩子绕着树根进行一次左旋。
    • 左右旋:
      • 让树根左孩子的右孩子绕着树根的左孩子进行一次左旋。
      • 然后再让所得的树根左孩子绕着树根进行一次右旋。
  • 运用这些平衡手段的条件
  • 旋转发生的条件:
    • 左右子树的高度差为二,旋转有两种::单旋转,双旋转。无论单旋转还是双旋转,都满足先进行与深度较高的子树同名(右子树对右旋转)旋转,如果是双旋转则随后进行异名(右子树对左旋转)旋转
    • 单旋转发生在:
    • ①插入时:
      • 插入的节点在不平衡点的左子树的左子树上(左单旋);在不平衡点的右子树的右子树上(右单旋)
    • ②删除时:
      • 删除左子树的节点导致该点不平衡且其右子树的右子树存在时(右单旋);删除右子树的节点导致该点不平衡且其左子树的左子树存在时(左单旋)
    • 双旋转发生在:
    • ①插入时:
      • 插入的节点在不平衡点的左子树的右子树上(左右旋);在不平衡点的右子树的左子树上(右左旋)
    • ②删除时:
      • 删除左子树的节点导致该点不平衡且其右子树的右子树不存在时(右左单旋);删除右子树的节点导致该点不平衡且其左子树的左子树不存在时(左右单旋)
  • 实现二叉查找树:红黑树
  • 红黑树是一个更高效的检索二叉树,因此常常用来实现关联数组。典型地,JDK 提供的集合类 TreeMap 本身就是一个红黑树的实现。
  • 红黑树控制结点颜色的规则如下:
    • 性质 1:每个节点要么是红色,要么是黑色。
    • 性质 2:根节点永远是黑色的。
    • 性质 3:所有的叶节点都是空节点(即 null),并且是黑色的。(性质 3 中指定红黑树的每个叶子节点都是空节点,而且叶子节点都是黑色 Java 实现的红黑树将使用 null 来代表,因此遍历红黑树时将看不到黑色的叶子节点,反而看到每个叶子节点都是红色的。)
    • 性质 4:每个红色节点的孩子结点都是黑色。(从每个叶子到根的路径上不会有两个连续的红色节点)
    • 性质 5:从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点。(红黑树从根节点到每个叶子节点的路径都包含相同数量的黑色节点,因此从根节点到叶子节点的路径中包含的黑色节点数被称为树的“黑色高度”。)
    • 红黑树能够以O(log2(N))的时间复杂度进行搜索、插入、删除操作。此外,任何不平衡都会在3次旋转之内解决。这一点是AVL所不具备的。

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

  • 问题1:不明白书中removeElement方法中部分代码的意思。书中解释是:

    如果被删除结点有两个孩子,则返回中序后继者(因为相等元素会放到右边)

代码是

  • 问题1的解决及过程:

    • 当结点的左右子树都不空的时候,一般的删除策略是用其右子树的最小数据来代替要删除的结点数据,并使得要删除子树的双亲结点指向找好的替代结点的子结点。
    • 老师在课堂上讲了另一种解决办法: 当结点的左右子树都不空的时候,找到该结点的前驱结点,然后将其前驱结点(用其左子树的最大数据)作为替代结点,然后让要删除子树的双亲结点指向替代结点的子结点。
    • 前驱结点:该结点左子树中的最大数据所在结点。
    • 后驱结点:该结点右子树中最小数据所在节点。
    • 总体来讲:一棵二叉查找树经过中序遍历后是一个有序的、从小到大的列表。
  • 问题2:高度深度究竟有什么区别?之前在学第十章:树的时候曾和仇夏同学讨论过,但是没有得到明确的结果。当时老师上课讲的是深度的概念,而且从root开始以1来计算、而书本上讲的是树的高度的概念,树的高度是从跟结点到叶子结点之间的的最远路径长度,并且从root开始以0来计算。???
  • 问题2的解决:
    • 高度和深度一组相反的概念
    • 高度是指当前结点到叶子结点的最长路径,如所有叶子结点的高度都为0。
    • 深度则是指从根结点到当前结点的最大路径长度,如根结点的深度为0。
  • 所以,书上的讲解和老师的讲解其实都没有问题,知识思维理解上的问题。高度就是从要计算的结点开始寻找最远路径长度,深度就是从根结点到该结点的最大路径长度;在一棵树中,高度+深度 = 树中最远的路径长度。
  • 问题3:红黑树的addElement操作和removeElement操作看书时没有看太懂,好多疑惑。
  • 问题3的解决:通过周五早上老师上课的讲解,觉得还是听懂了一些的。这里稍加总结并配上老师的图。

代码实现时的问题作答 Exercise

  • 问题1:这周的代码补全很容易理解,在我做完补全操作后,我又和我的小伙伴仇夏同学订对了一波,于是我们发现了之前写的findMin以及findMax由于使用了之前写的removeMin和removeMax的思路,在写的时候其实有冗余代码。
  • 问题1的解决:删掉冗余代码。
  • 问题2: 实现add自我递归时出现的错误。首先是死递归,其次是出现了一行不明错误提醒。

  • 问题2的解决:先是来解决不明错误提醒,我通过百度后得知:

    原来Junit4中的测试方法的方法名首字母不能大写!!!

  • 通过修改代码后,我发现是因为我的node直接定义成了root,所以在每次递归的时候又开始之前的路,就变成了死递归,在删除代码·node=root后测试就出来了。但是由于toString问题没有解决,我用了中序遍历,但是还是出现了很令人伤心的结果,但通过找最大最小值,看的出来,我的插入方法已经成功将1插入了二叉查找树。
  • 问题3:上述问题2没有实现树型输出,主要问题就在我的toString方法中,但是我没有实现树形状的toString方法。
  • 问题3的解决:通过询问郭恺同学,借用了上周运算表达树中PrintTree的输出方法,稍作修改,就很完美的实现了树形的正确输出啦。

上周测试活动错题改正 Correction

  • The binary tree shown above is balanced.
    A .True
    B .False
  • 这道题我真的没有找到图,所以不知道她平不平衡。所以没啥好说的······给出的答案是true。

    码云链接

代码量(截图)

结对及互评Group Estimate

点评模板:

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

    • 20172301:博客呢我还没看到,但是下课后该同学留下来去答疑了,说明肯定有认真学习呦。
    • 20172304: 对于学习知识点掌握应该是挺好的,上课时对问题反应很迅速。本次博客教材学习中的问题和解决过程和代码问题都写的不是很详细,望继续改进。

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

      今天早上的经济学原理课程听得我很快乐。范老师十分幽默风趣,讲到了:在我们面临稀缺而选择实现效益最大化时就要体现自身价值,在“万类霜天竞自由”的场景下是需要我们去保持核心竞争力的。
      上课时我进行了自我的反问。从前,我从不想将自己放在与人竞争的位置,只想尽量做好自己。至少在我看来,同人相比较是件不光彩的事,每个个体没有相同的轨迹和需要被比较的必要。但现在想来,在生活的时时刻刻我又何尝不是处在竞争的环境下呢?所以,做好自己并不去打扰别人的努力,自我奋斗去实现自身价值即可。至于对待结果的态度,从一而终。
      二叉查找树这一章很有意思也不太容易完全理解但是呢,事物的发展不是直线式前进的,而是螺旋式上升的。所以我们既要看到道路的曲折,也要看到前途的光明!

      学习进度条Learning List

      代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积)
      目标 5000行 30篇 400小时
      第一周 0/0 1/1 8/8
      第二周 621/621 1/2 12/20
      第三周 678/1299 1/3 10/30
      第四周 2734/4033 1/4 20/50
      第五周 1100/5133 1/5 20/70
      第六周 1574/6707 2/7 15/85
      第七周 1803/8510 1/8 20/105

参考资料Reference

原文地址:https://www.cnblogs.com/LXY462283007/p/9896551.html

时间: 2024-10-28 14:46:46

20172328 2018-2019《Java软件结构与数据结构》第七周学习总结的相关文章

20172305 2018-2019-1 《Java软件结构与数据结构》第一周学习总结

20172305 2018-2019-1 <Java软件结构与数据结构>第一周学习总结 教材学习内容总结 本周内容主要为书第一章和第二章的内容: 第一章 软件质量: 正确性(软件达到特定需求的程度) 可靠性(软件发生故障的频率和危害程度) 健壮性(很好处理错误情况的情况) 可用性(用户在软件中掌握和运行任务的容易程度) 可维护性(软件进行修改的容易程度) 可重用性(软件组件可被其他软件系统开发使用的容易程度) 可移植性(软件组成可用于多种计算机环境中的容易程度) 运行效率(不浪费资源的情况下软

2018-2019-20172321 《Java软件结构与数据结构》第九周学习总结

2018-2019-20172321 <Java软件结构与数据结构>第九周学习总结 教材学习内容总结 第15章 图 无向图 图由顶点和边组成. 顶点由名字或标号来表示,如:A.B.C.D: 边由连接的顶点对来表示,如:(A,B),(C,D),表示两顶点之间有一条边. 无向图:与树类似,图也由结点和这些结点之间的连接构成.这些结点是顶点,而结点之间的链接是边.无向图是一种边为无序结点对的图.于是,记做(A,B)的边就意味着A与B之间有一条从两个方向都可以游历的连接.边记作(A,B)和记作(B,A

20172328 2018-2019《Java软件结构与数据结构》第六周学习总结

20172328 2018-2019<Java软件结构与数据结构>第六周学习总结 概述 Generalization 本周学习了第十章:非线性集合与数据结构--树.主要讨论了树的使用和实现,以及考察实现和使用树的实例. 教材学习内容总结 A summary of textbook 树(tree):树是一种非线性结构,其元素被组织成了一个层次结构.下面是树的术语,了解一下吧! 树有一个包含结点(node)和边(edge)的集构成,其中的元素被储存在这些结点中,边则将一个结点和另一个结点连接起来.

20172328 2018-2019《Java软件结构与数据结构》第八周学习总结

20172328 2018-2019<Java软件结构与数据结构>第八周学习总结 概述 Generalization 本周学习了二叉树的另一种有序扩展?是什么呢?你猜对了!ヾ(?°?°?)??就是堆.本章将讲解堆的链表实现and数组实现,以及往堆中添加元素或从堆中删除元素的算法:还将介绍对的一些用途,包括基本使用和优先队列. 教材学习内容总结 A summary of textbook 堆(heap)就是具有两个附加属性的一颗二叉树: 第一点:它是一颗完全二叉树 ,即叶子节点都在最后一层靠左侧

201871010104-陈园园 《面向对象程序设计(java)》第六——七周学习总结

201871010104-陈园园 <面向对象程序设计(java)>第六——七周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业要求在哪里 https://www.cnblogs.com/lily-2018/p/11441372.html 作业学习目标 (1) 理解继承的定义: (2) 掌握子类的定义要求 (3) 掌握多态性的概念及用法: (4) 掌握抽象类的定义及用途. 第一部分:总结理论知识 1.类.超类和子类: a

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

20172306 2018-2019 <Java程序设计与数据结构(下)>第一周学习总结 教材学习内容总结 第一章 概述 (程序=数据结构+算法 软件=程序+软件工程) 1.1 软件质量 软件工程师一门关于高质量软件开发的技术和理论的学科 软件工程的目标:1.解决正确性问题 2.按时且在预算之内给出解决方案 3.给出高质量的解决方案 4.以合情合理的方式完成上面的事情 高质量软件的特征 正确性:我认为是我们所做的都是为了解决一个正确性问题. 可靠性:降低软件的故障程度和概率 健壮性:可以很好地

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

20172306<Java程序设计>第九周学习总结 教材学习内容总结 第十一章: try-catch语句.其中还有finally语句.try是进行某些操作,catch是捕获异常,并通过某些异常来进行某些操作.finally是无论是否有异常都会进行的语句.可以没有catch语句. 异常的传递.我觉得传递,主要是某地方的异常是由其他的方法引起的,异常就会传递到那个方法上.书中的例子可以很好的表现出来. IO异常.书中的内容主要是围绕异常来写.老师在蓝墨云中有写有关IO更为详细的内容.例如创建文件,

20172302 《Java软件结构与数据结构》第四周学习总结

2018年学习总结博客总目录:第一周 第二周 第三周 第四周 教材学习内容总结 第六章 列表 1.列表是对象的有序集合,在 List 界面中定义. List 接口表示集合框架中的列表.列表可以具有重复的元素.并且我们可以在列表中存储多个空值. 2.列表集合 是一种概念性的表示方法,其思想是使事物以线性列表的方式进行组织,就像栈和队列一样,列表也可以使用数组和链表来实现.列表集合没有内在的容量大小,它可以随着需要而增大.列表集合更一般化,可以在列表的中间和末端添加和删除元素. 3.列表可以分为有序

20172308《Java软件结构与数据结构》第四周学习总结

教材学习内容总结 第 6 章 列表 一. 列表集合 列表集合:一种概念性表示法,思想是使事物以线性列表的方式进行组织 特点: 列表集合没有内在的容量大小,它可以随着需要而增大 列表集合更具一般化,可以在列表的中间和末端添加和删除元素 列表也可以使用链表或数组实现 类型: 有序列表:元素按照元素的某种内在特性进行排序 无序列表:元素间不具有内在顺序,元素按照它们在列表中的位置排序 索引列表:其元素可以用数字索引来引用(顺序由使用者决定) 二. Java API没有任何类能直接实现以上描述的有序列表