2018年学习总结博客总目录:第一周 第二周 第三周 第四周 第五周 第六周 第七周
html
1.二叉查找树是一种含有附加属性的二叉树,该属性即其左孩子小于父节点,而父节点又小于等于其右孩子。二叉查找树的一个示意图:
在二叉查找树中:
(01) 若任意节点的左子树不空,则左子树上全部结点的值均小于它的根结点的值;
(02) 任意节点的右子树不空,则右子树上全部结点的值均大于它的根结点的值;
(03) 任意节点的左、右子树也分别为二叉查找树。git
2.二叉查找树的接口类继承自二叉树的接口类BinaryTreeADT,在其基础上补充了一些操做方法,代码以下:算法
public interface BinarySearchTreeADT<T> extends BinaryTreeADT<T> { public void addElement(T element); //往树中添加一个元素 public T removeElement(T targetElement); // 从树中删除一个元素 public void removeAllOccurrences(T targetElement); // 从树中删除所指定元素的任何存在 public T removeMin(); //删除树中最小元素 public T removeMax(); // 删除树中最大元素 public T findMin(); //返回一个指向树中最小元素的引用 public T findMax(); //返回一个指向树中最大元素的引用 }
3.链表实现二叉查找树
LinkedBinarySearchTree类它继承自LinkedBinaryTree类,是对LinkedBinaryTree类的一种拓展,同时它还实现了BinarySearchTreeADT接口类。数据结构
public LinkedBinarySearchTree() { super(); }
public LinkedBinarySearchTree(T element) { super(element); if (!(element instanceof Comparable)) throw new NonComparableElementException("LinkedBinarySearchTree"); }
addElement操做
1.树空,新元素成为树的根结点;
2.非空,与树根元素进行比较;
(1)小于根元素:①左孩子为null:新元素成为根的左孩子;②左孩子不为null:遍历根的左孩子,再次进行比较操做;
(2)大于等于根元素:①右孩子为null:新元素成为根的右孩子;②右孩子不为null:遍历根的右孩子,再次进行比较操做;数据结构和算法
removeElement操做
找到被删除结点的替换结点,删除被删除结点,替换为替换结点。
选择替换结点的三种状况:
(1)被删除结点没有孩子,replacement返回null;
(2)被删除结点有一个孩子,replacement返回这个孩子;
(3)被删除结点有两个孩子,replacement返回中序后继者;(处于根结点右子树上)
示意图:
ide
public void removeAllOccurrences(T targetElement) throws ElementNotFoundException { removeElement(targetElement); try { while (contains((T)targetElement)) removeElement(targetElement); } catch (Exception ElementNotFoundException) { } }
4.用有序列表实现二叉查找树
LinkedBinarySearchTree类有不少方法与有序列表的方法之间存在着一一对应关系函数
5.平衡二叉查找树
若是二叉查找树不平衡,那么其效率可能比线性结构还要低。接下来讨论一些经常使用的平衡技术。
(1)右旋
使用条件:根结点左孩子的左子树过长致使不平衡
使用方法:①树根左孩子元素成为新的根元素②原树根元素称为新树根的右孩子元素③使原树根左孩子的右孩子,成为原树根的新的左孩子
(2)左旋
使用条件:根结点右孩子的右子树过长致使不平衡
使用方法:①树根右孩子元素成为新的根元素②原树根元素称为新树根的左孩子元素③使原树根右孩子的左孩子,成为原树根的新的右孩子
(3)右左旋
使用条件:根结点的右孩子的左子树过长致使不平衡
使用方法:①先让右孩子的左孩子,绕树根右孩子进行一次右旋②树根的新的右孩子绕树根左旋一次
(4)左右旋
使用条件:根结点的左孩子的右子树过长致使不平衡
使用方法:①先让左孩子的右孩子,绕树根左孩子进行一次左旋②树根的新的左孩子绕树根右旋一次学习
6.AVL树
平衡因子:右子树的高度减去左子树的高度。.net
平衡因子<-1 | 平衡因子>1 | |
---|---|---|
孩子的平衡因子<=-1 | 右旋 | 右左旋 |
孩子的平衡因子>=1 | 左右旋 | 左旋 |
7.红黑树
红黑树的特性:
(1)每一个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每一个叶子节点(Null)是黑色。 [注意:这里叶子节点,是指为空(NULL)的叶子节点!]即每一个空结点为黑色,也即默认结点为黑色
(4)若是一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的全部路径上包含相同数目的黑节点。
红黑树示意图:
3d
问题1:关于教材242页中所说的“据此咱们能够论证具备n个节点红黑树的最大高度约为2*logn”,这句话不能理解,从哪里论证而来的结果?
问题1解决方案:本身想试着推一下,推的话我想的是从其知足红黑树的特征下手,但试了一会没有结果,因而就从网上查找资料,给出的一个办法是用概括总结法去证实这一结论。
"一棵含有n个节点的红黑树的最大高度约为2*logn"等价于“高度为h的红黑树,它的包含的节点个数至少为2^(h/2)个”。
从某个节点x出发(不包括该节点)到达一个叶节点的任意一条路径上,黑色节点的个数称为该节点的黑高度(x's black height),记为bh(x)。关于bh(x)有两点须要说明:
第1点:根据红黑树的特性——从一个节点到该节点的子孙节点的全部路径上包含相同数目的黑节点可知,从节点x出发到达的全部的叶节点具备相同数目的黑节点。这也就意味着,bh(x)的值是惟一的!
第2点:根据红黑色的特性——若是一个节点是红色的,则它的子节点必须是黑色的可知,从节点x出发达到叶节点"所经历的黑节点数目">= "所经历的红节点的数目"。假设x是根节点,则能够得出结论"bh(x) >= h/2"。进而,咱们只需证实 "高度为h的红黑树,它的包含的内节点个数至少为 2^bh(x)个"便可。
到这里,咱们将须要证实的定理已经由"一棵含有n个节点的红黑树的高度至多为2log(n)" 转变成只须要证实"高度为h的红黑树,它的包含的内节点个数至少为 2bh(x)个"。
下面经过"数学概括法"开始论证高度为h的红黑树,它的包含的节点个数至少为 2^bh(x)个"。
(01) 当树的高度h=0时,内节点个数是1,bh(x) 为1,2^bh(x)也为 1。显然,原命题成立。
(02) 当h>0,且树的高度为 h-1 时,它包含的节点个数至少为 2^(bh(x)-1)。这个是根据(01)推断出来的!
下面,由树的高度为 h-1 的已知条件推出“树的高度为 h 时,它所包含的节点树为 2bh(x)”。
当树的高度为 h 时,
对于节点x(x为根节点),其黑高度为bh(x)。
对于节点x的左右子树,它们黑高度为 bh(x) 或者 bh(x)+1。
根据(02)的已知条件,咱们已知 "x的左右子树,即高度为 h-1 的节点,它包含的节点至少为 2^(bh(x)-1) 个";
因此,节点x所包含的节点至少为 ( 2^(bh(x)-1) ) + ( 2^(bh(x)-1) ) + 1 = 2^bh(x)。即节点x所包含的节点至少为 2bh(x)。
所以,原命题成立。
由(01)、(02)得出,"高度为h的红黑树,它的包含的内节点个数至少为 2^bh(x)个"。
所以,“一棵含有n个节点的红黑树的高度至多为2log(n)”。
问题2:关于红黑树的元素插入、删除
问题2解决方案:
插入
首先,咱们插入的结点设置颜色为red,若是其父节点为black,那么没有违背红黑树任何条件,插入便可,但若是其父节点为red,那么须要调整,由于红色结点的孩子颜色不能为红色。
插入一个结点时应该关注其叔叔结点?
由于在父结点为红色的状况下,咱们调整时一定要改动其父结点所构成的树颜色,而这里发生改变,那么必定致使祖父结点处的左右子树不能再知足“从一个节点到该节点的子孙节点的全部路径上包含相同数目的黑节点”,那么咱们须要对叔叔结点也进行改动,才能保持红黑树特性。
下面来看须要调整的三种状况(父结点为红色,此时祖父结点必为黑色,以父结点为祖父左孩子为例):
(1)叔叔结点为红色
此时咱们须要把叔叔结点d和父亲结点b都设为黑色,这样不改变祖父结点c下的“从一个节点到该节点的子孙节点的全部路径上包含相同数目的黑节点”特性;
但还需将祖父c结点设为红色(由于在从根结点到祖父往下的路径上多了一个黑结点),并将当前结点设为祖父结点,而后往上迭代进行;
(2)叔叔结点为黑色,且插入结点为父结点右孩子
此时需将插入结点绕其父结点b向左旋转,这步不改变树的各个路径上的黑结点数目,但仍不知足红色结点的孩子必为黑色,此时转换为(3)中状况;
为何要进行这一步转化?
由于咱们如今仅靠改变c的左子树上的颜色是不能保持红黑树的特性的。
(3)叔叔结点为黑色,且插入结点为父结点左孩子
如今,咱们先绕祖父结点c进行一次右旋,由于祖父结点c为黑色,此时b结点的右子树上要多一个黑色结点,同时仍不知足红色结点孩子都为黑色;
咱们这时需把b结点设为黑色,另再将其左右两个孩子结点a、c设为红色。
删除
删除操做比较复杂,本身理解还存在一些困难,再也不总结。
参考这篇博客学习红黑树的删除操做
问题1:课本代码BinarySearchTreeList类出现错误,错误类型为both methods have same erasure, yet neither overrides the other。
问题1解决方案:没见过这个错误,去网上查找资料,它的解释是泛型类型擦除与重载和覆盖问题,
先看一段代码
public class Father { void test(Object o){} } class Son<T> extends Father{ void test(T o){}//编译错误! }
这段代码会报一个编译错误,both methods have same erasure, yet neither overrides the other。
这个错误的意思是,两个方法在类型擦除后,具备相同的原生类型参数列表,可是也不能覆盖另外一个方法。
泛型类型在编译后,会作类型擦除,只剩下原生类型。如参数列表中的T类型会编译成Object,可是会有一个Signature。
尽管两个test方法具备相同的字节码,可是类型参数信息用 一个新的签名(signature) 属性记录在类模式中。JVM 在装载类时记录这个签名信息,并在运行时经过反射使它可用。
这就致使了这个方法既不能做为覆盖父类test方法的方法,也不能做为test方法的重载。
看过以后没感受,不太懂它在说什么?又看了好几遍,才终于有些明白,个人那个错误也是将个人方法中参数类型改成Object类型,但那样仍是会报错,由于它的类型擦除后,父子类两个重名方法并不能覆盖。知道这以后,又查看本身的代码,终于找到了是在个人OrderedListADT类中出了问题,即OrderedListADT类在继承ListADT类时没有写出泛型,改过以后解决问题。
上周代码行数为12499行,如今为13751行,本周共1252行。
上周考试没有错题
博客中值得学习的或问题:本周博客内容很是详细,尤为是有关红黑树的介绍部分以及教材代码理解部分。
结对学习内容:第十一章——二叉查找树。
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/1 | 15/15 | |
第二周 | 572/572 | 1/2 | 16/31 | |
第三周 | 612/1184 | 1/3 | 13/44 | |
第四周 | 1468/2652 | 2/5 | 13/57 | |
第五周 | 1077/3729 | 1/6 | 14/71 | 初步理解各个排序算法 |
第六周 | 1087/4816 | 1/7 | 17/88 | 认识树结构 |
第七周 | 1252/6068 | 1/8 | 19/107 | 平衡二叉树、AVL树、红黑树 |