20172310 2017-2018《程序设计与数据结构》(下)第七周学习总结

20172310 2017-2018《程序设计与数据结构》(下)第七周学习总结

教材学习内容总结

本章学习的是二叉查找树


11.1 概述

  • 二叉查找树(binay scarch tree)是种带有附加属性的二叉树,即对树中的每个结点,其左孩子都要小于其父结点,而父结点又小于或等于其右孩子。
  • 二叉查找树的定义是上章中讨论的二叉树定义的扩展。因此,下面的操作是二叉树中已定义的那些操作的补充。二叉查找树和平衡二叉查找树的接口是一样的程序列表。


11.2 用链表实现二叉查找树

  • BinaryTreeNode在二叉查找树中也用来表示树中的每个节点,每个BinaryTreeNode对象要维护一个指向结点所存储元素的引用,另外还要维护指向结点的每个孩子的引用。

  • addElement 操作:addElement方法根据给定元素的值,在树中的恰当位置添加该元素。
    添加元素位置的几种情况

    • 如果这个元素不是Comparable,则addElement方法会抛出NoComparableElementException异常。
    • 如果树为空,则这个新元素就将成为根结点。
    • 如果树非空,且它小于根结点中存储的那个元素且根的左孩子为null, 则这个新元素就将成为根的左孩子。如果这个新元素小于根结点中存储的那个元素且根的左孩子不是null, 则会遍历根的左孩子,并再次进行比较操作。
    • 如果这个新元素大于或等于树根存储的那个元素且根的右孩子为null, 则这个新元素会成为根的右孩子。如果这个新元素大于成等于树根处存储的那个元素且根的右孩子不是null,则会遍历根的右孩子,并再次进行比较操作

  • 一旦定义了希望构造的树的类型和树的使用方式,也就能够定义出该树的接口和各种实现。

  • removeElement操作

    • removeElemcnt方法必须选出另一个结点来代替要被删除的那个结点。private方法replacement返回指向一个结点的引用,该结点将代替要删除的结点。
      选择替换结点的三种情况如下:
    • 如果被删除结点没有孩子,则replacement返回null.
    • 如果被删除结点只有一 个孩子, 则replacement返回这个孩子。
    • 如果被删除结点有两个孩子,则replacement 会返回中序后继者(相等元素会放到右边)。
      且这个后继者不可能有左孩子节点,因为如果有左孩子节点则它的左孩子节点会成为那个后继者,而不是它,因此后继者要么没有孩子节点,要么只有右孩子。


二叉查找树的最右侧结点会存放最大元素,而其最左侧结点会存放最小元素.

  • removeMin操作
    按照二叉树的定义,最小元素在二叉查找树中只会存在于最左边的位置,最左的位置分为有3种可能情形:

    • 如果树根没有左孩子,则树根就是最小元素,而树根的右孩了会变成新的根结点。
    • 如果树的最左侧结点是片叶子, 则这片叶子就是最小元素, 这时只需设置其父结点的左孩子引用为mull即可。
    • 如果树的最左侧结点是个内部结点,则需要设置其父结点的左孩 子引用指向这个将删除结点的右孩子。
  • removeMax操作同理

11.3用有序列表实现二叉查找树

  • 树的主要使用之一就是为其他集合提供高效的实现。

  • BinarySearchTreeList实现的分析:BinarySearchTreeList 的实现是一种任何结点的最大深度为log2(n)(其中n为树中存储的元素数目)的平衡二叉查找树。所以,add 操作和remove操作都要求重新平衡化树。
  • 虽然树实现中的有些操作更为有效,比如removeLast、last 和contains:但在利用树实现时,也有一些操作会变得低效,比如removeFirst和first。

11.4平衡二叉查找树

  • 蜕化树:如同链表一般,只有单边的子树。实际效率比链表还低。
  • 如果二叉查找树不平衡,其效率可能比线性结构的还要低。
  • 平衡二叉树:任何一个节点的左右子树深度差不超过1.通过这个限定,阻止了二叉树的左右子树深度差较大的情况,维持了二叉树的稳定。
  • 平衡化技术中的一些方法:
    • 右旋:节点插入在最小不平衡树的右子树的右子树上面。 

    • 左旋:节点插入在最小不平衡节点的左子树的左子树上。

    • 右左旋:节点插入在最小不平衡树的右子树的左子树上面。
    • 左右旋:节点插入在最小不平衡节点的左子树的右子树上面
    • 用法总结:从发生不平衡的结点起,沿刚才回溯的路径取直接下两层的结点,如果这三个结点在一条直线上,则采用单旋转进行平衡化,如果这三个结点位于一条折线上,则采用双旋转进行平衡化。如图:

这是一篇很好的参考资料:数据结构——平衡二叉树

  • 为了解决上述二叉排序树这种左右子树深度因为插入或删除结点而不均匀的情况引入了两种方式红黑树和AVL树。

  • AVL树:是一种平衡二叉树的变体,其中最重要的一个概念是平衡因子:右子树的高度减去做紫薯的高度称为该结点的平衡因子。其旋转方式同上。
  • 红黑树:
    1、根节点是黑色。
    2、如果一个节点是红色的,则它的子节点必须是黑色的。
    3、从树根到树叶的所有路径上包含相同数目的黑色结点。
    4、每个节点或者是黑色,或者是红色。
    5、每个空结点为黑色。

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

  • 问题1:对课本removeElement方法的代码理解有困难,主要是后面的删除元素的图给错了,于是理解了半天。
  • 问题1解决方案:其实最重要的是replacement代码段的理解,课本给出了三种情况的分类,“如果被删除结点有两个孩子,则replacement 会返回中序后继者”这种类型的时候中序后继者是什么意思呢?我结合着课本给出的删除结点的示意图来理解。

如果删除的节点是10,它有左右孩子,中序遍历是先查左孩子,再是该节点,然后是右孩子,中序遍历查找的顺序是7,10,13,15 。现在10是当前所指向的结点,所以从这个步骤开始,继续接下去的遍历,也就是看下一个查找的元素,然后返回它,也就是返回13 。

 private BinaryTreeNode<T> replacement(BinaryTreeNode<T> node)
    {
        BinaryTreeNode<T> result = null;
        // 如果被删除结点没有孩子
        if ((node.left == null) && (node.right == null))
            result = null;
        //被删除的结点只有一个孩子,则返回孩子
        else if ((node.left != null) && (node.right == null))
            result = node.left;

        else if ((node.left == null) && (node.right != null))
            result = node.right;
        //被删除结点有两个孩子,就要找的比左边孩子小,但比该结点大的孩子。
        else
        {
            BinaryTreeNode<T> current = node.right;//创建一个结点current,存放当前节点的右孩子
            BinaryTreeNode<T> parent = node;

            while (current.left != null)//中序遍历找到下一个结点
            {
                parent = current;
                current = current.left;
            }

            current.left = node.left;//将被删除结点的左孩子链到找到的这个结点的左边

            if (node.right != current)//如果这个找到的节点不是原要被删除的结点的右孩子
            {
                parent.left = current.right;//这时current.right为null,parent.left从被找到的结点变为null
                current.right = node.right;
            }

            result = current;
        }

        return result;
    }
  • 问题2:对课本中红黑树的操作完全看不懂。
  • 问题2解决方案:看完了课本对于红黑树操作的讲解,我不得不说,这些字我都认识,可放在一起我怎么就理解不了呢?(〃>皿<)
    对课本上给出的合法的红黑树的例子,我也表示怀疑,所以就去百度上找了一些资料来看看。
  • 红黑树中元素的插入:
    1.首先插入结点。插入的结点定为红色( 因为将插入的节点着色为红色,不会违背"从树根到树叶的所有路径上包含相同数目的黑色结点。",少违背一条特性,就意味着我们需要处理的情况越少)。
    2.插入结点后的红黑树仍是一棵二叉查找树,但是插入后变得不再平衡了。之后重新平衡化或者说重新着色的过程则是一种迭代的过程,所以插入节点后,我们要做的就是将破坏红黑树规则的结点通过重新着色上移到别的结点。
    3.接下来是分情况讨论如何变色和旋转,使其重新平衡。
    (1)其父节点为black,这种情况下没有违背红黑树任何条件,直接插入即可(包含被插入的节点为根节点的情况);
    (2)插入的结点的父节点是red的情况下,又可根据叔叔结点的case划分为三种情况来处理;
    - case1:当叔叔结点也为红色时,第一,先将父节点和叔叔结点变为black;第二,将祖父结点变为red;最后运用递归继续改变更底层的结点。

                  - case2:当叔叔结点是black时,如果当前结点是父节点的左孩子,则将父节点染为black,在把祖父结点染为red,最后以祖父节点为支点进行右旋。

                  - case3:当叔叔结点是black时,而当前结点是父节点的右孩子,则以该插入的结点的父节点作为当前节点进行左旋,变为case2进行处理。

  • 红黑树中元素的删除
    我之前已经总结过,在一棵平衡二叉树要删除一个结点有三种情况。
    这三种情况在红黑树中一样,但我们需要做的是将删除后的二叉树重新平衡和染色,现在,又可分为以下几种情况:
    1)删除的结点为叶子节点,然后判断该节点是否为黑色的,若为true,则在删除后会导致黑高不相等。于是需要对红黑树进行调整。
    2)删除的结点有一个孩子节点,此时直接使用其孩子节点代替z节点,然后判断删除的节点是否为黑,若为true,则对红黑树进行调整。
    3)删除的结点有左右孩子节点,这时首先找到该节点的后继节点,有两种情况:第一种情况是y是z的右孩子节点,第二种情况是y不是z的右孩子节点。

调整的方式:

  1. 当删除情况为第一二种且结点为black时,我们可以将替代原结点的节点x再加一种再额外增加一种黑色。(网上的资料都是这样解释的,但是而额外增加的到底是怎么回事我还没有研究透彻,如果弄懂了后续再修改╭(╯^╰)╮)

在第三种情况中,通过使用z的后继节点y替换z节点,然后使用y的右孩子x来填补y的位置。在此过程需要将节点y进行移动,由于移动之后的y节点保持原来z节点的颜色,而x节点在代替y节点之后可能会出现问题,当然只会在y节点是黑色的情况下才会出现问题,当y节点为红色时,移动时红黑树的性质不会被破坏,y节点为黑色时,一定会出现黑高的不相等,并且也可能会出现两个连续的红色节点。这时需要对其进行下一步调整。

红黑树的删除
这是关于删除的一份资料,跟着这里面看可以理解很多,但自己还是有些内容理解不了,主要是删除比插入的情况更多而且更复杂,理解起来还是很有难度的。

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

  • 问题1:XXXXXX
  • 问题1解决方案:XXXXXX
  • 问题2:XXXXXX
  • 问题2解决方案:XXXXXX
  • ...

代码托管

(statistics.sh脚本的运行结果截图)

上周考试错题总结

  • 上周无错题(ノ ̄▽ ̄)

结对及互评

点评:

  • 本周结对学习情况

    • 结对同学学号1
    • 结对学习内容
      • XXXX
      • XXXX
      • ...
  • 博客中值得学习的或问题:
    • xxx
    • xxx
    • ...
  • 代码中值得学习的或问题:
    • xxx
    • xxx
    • ...

点评过的同学博客和代码

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

这周的学习是建立在上周所学知识的基础上的,果然基础要打好,后面的学习才会更有效率。不得不批评一下淘宝买来的课本了,太坑爹了,图错了好几个,我一直研究,一直觉得不对,后来事实证明我是正确的,不过还是浪费了一些时间在这个上面。双周的课程比单周要少一些,所以这周自学Java的时间要多一些,果然知识都是靠时间换来的。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积)
目标 5000行 30篇 400小时
第一周 0/0 1/1 10/10
第二周 326/326 1/2 18/28
第三周 784/1110 1/3 25/53
第四周 2529/3638 2/5 37/90
第五周 1254/4892 2/7 20/110
第六周 1403/6295 2/9 32/142
第七周
  • 计划学习时间:30小时
  • 实际学习时间:XX小时
  • 改进情况:

参考资料

原文地址:https://www.cnblogs.com/Qiuxia2017/p/9880422.html

时间: 2024-10-10 06:39:53

20172310 2017-2018《程序设计与数据结构》(下)第七周学习总结的相关文章

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

20172310 2017-2018-2 <程序设计与数据结构>第十周学习总结 教材学习内容总结 本周学习的是第十三章 集合与数据结构 集合是一种对象,类似于保存其他对象的存储库.我们常用集合表示一个专用于保存元素的对象,并且该对象还提供增添,删除等管理 所保存元素的服务. 集合是同构的,意味着这种集合保存类型全部相同的对象;另一些集合则是异构的,即这种集合可以保存各种类型的 对象. 分离接口与实现: 1.一个抽象数据类型(ADT)是由数据和在该数据上所实施的具体操作构成的集合.一个ADT有名

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

学号20172328<程序设计与数据结构>第七周学习总结 第九章教材学习内容总结 1.继承的概念: 继承是在父类和子类之间建立一种"是"的关系. 用于派生新类的原始类称为父类.超类或基类,被派生出的类就称为子类或者亚类. 2.继承具有单向性.java中用extends来表示新类由现有类派生. 3.protected修饰符:当变量声明为protected可见性时,子类就可以引用它,并且使父类保持了一定的封装性. (在UML图中,用#表示protected可见性.) 4.sup

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

20172313 2017-2018-2 <程序设计与数据结构>第七周学习总结 教材学习内容总结 学习了如何去创建一个子类. 学习了使用protected修饰符让子类能够访问一个父类公共变量和使用保留字super来调用父类的构造方法. 学习了如何对父类的方法进行重写. 初步学习了类层次结构,了解了Object类和抽象类以及接口的层次结构. 学习了子类怎样通过一个其他方法来引用父类中的方法和变量以及常量. 初步学习了类间继承关系的设计. 教材学习中的问题和解决过程 问题1:在学习接口的时候就有这

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

20172324 2017-2018-2 <程序设计与数据结构>第七周学习总结 教材学习内容总结 编写类是定义一组类似的对象:类建立了对象的特征和行为,但没有位声明的变量预留内存空间(除非所声明的变量是静态的) 继承是从现有类派生新类的过程,并且是一种强有力的软件开发技术. super可用来访问构造方法.父类的构造方法不能直接按名字调用,但可用super引用调用父类的构造方法. 当子类和父类有相同的方法名时,子类方法将重写父类方法,子类方法优先.但是子类不能重写final方法. 子类不可以重写

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

20172313 2018-2019-1 <程序设计与数据结构>第七周学习总结 教材学习内容总结 概述 二叉查找树:二叉查找树是一种含有附加属性的二叉树,即其左孩子小于父结点,而父结点又小于或等于右孩子.二叉查找树的定义是二叉树定义的扩展. 二叉查找树的各种操作 操作 说明 addElement 往树中添加一个元素 removeElement 从树中删除一个元素 removeAllOccurrences 从树中删除所指定元素的任何存在 removeMin 删除树中的最小元素 removeMax

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

20172333 2018-2019-1 <程序设计与数据结构>第七周学习总结 教材学习内容总结 <Java软件结构与数据结构>第十一章-二叉查找树 一.二叉查找树的概念及相关方法 ①思路:二叉查找树与普通的二叉树的区别类似于有序链表与无序链表的差别,二叉查找树因为实现了Comparable接口的类型的对象,所以该二叉树在添加数据到树中的时候就会自动排序,将大于根节点的数据放在右结点,反之则保存在左结点.这样排序好的二叉树方便查找所以叫二叉查找树. ②方法: public inte

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

20172314 2017-2018-2 <程序设计与数据结构>第七周学习总结 教材学习内容总结 创建子类: 继承就是从现有类派生新类的过程,通过在子类的声明头中写public class 子类名 extends 父类名;来实现. 特别注意: 子类的实例化并不依赖于父类的实例化. 继承具有单向性,父类不能引用子类中声明的变量和方法. 构造方法不会继承. protected修饰符: 父类中的公共方法可以在子类中通过名称访问,若子类想访问其私有方法,那么父类的方法就必须声明为protected可见

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

20172322 2017-2018-2 <程序设计与数据结构>第七周学习总结 教材学习内容总结 学会了使用UML图来表示各类间关系,UML也可以使得编程的思路变得清晰.例如#代表可继承,+代表public,-代表private. 学会了使用super引用父类的构造方法,因为父类的构造方法不会继承给子类,但如果子类需要继承父类的构造方法需要使用super. 了解到当子类和父类有相同的方法名和签名时,子类方发将重写父类方法,例如书上例9.7.9.8,它的存在允许两个有继承关系的对象按照同名规则使

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

20172327 2018-2019-1 <程序设计与数据结构>第七周学习总结 教材学习内容总结 第十一章 二叉查找树 概述 1.二叉查找树是一种带有附加属性的二叉树,即对树的每个结点都有左结点小于父结点,右结点小于或等于父结点. 2.二叉查找树的定义是二叉树定义的扩展. 3. | 方法 | 描述 | | -------- | :------------------------------------------: | | addElement | 往树中添加一个元素 | | removeEl

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

20172315 2018-2019-2 <程序设计与数据结构>第七周学习总结 教材学习内容总结 二又查找树是一种含有附加属性的二又树,即其左孩子小于父结点,而父结点又小于或等于右孩子. 每个BinaryTreeNode对象要维护一个指向结点所存储元素的引用,另外还要维护指向结点的每个孩子的引用. 从二又查找树中删除一个元素时,必须推选出另一个结点来代替要被删除的那个结点. 二又查找树的最右侧结点会存放最大元素,而其最左侧结点会存放最小元素. 如果二又查找树不平衡,其效率可能比线性结构的还要低