《 常见算法与数据结构》符号表ST(4)——二叉查找树删除 (附动画)
来源:互联网 发布:黑页源码 编辑:程序博客网 时间:2024/05/20 06:08
符号表ST(4)——二叉查找树删除 (附动画)
本系列文章主要介绍常用的算法和数据结构的知识,记录的是《Algorithms I/II》课程的内容,采用的是“算法(第4版)”这本红宝书作为学习教材的,语言是java。这本书的名气我不用多说吧?豆瓣评分9.4,我自己也认为是极好的学习算法的书籍。
通过这系列文章,可以加深对数据结构和基本算法的理解(个人认为比学校讲的清晰多了),并加深对java的理解。
我们之前介绍了二叉查找树和它的基本操作,唯独一个操作没介绍,就是删除操作,这里,我们重点介绍删除操作。
1 一种偷懒的方式
还记得我们曾经在符号表的介绍中说过的一种删除方式吗?
我们可以不删除,而是把需要删除的节点的value设为null(这里我们叫放“墓碑”)。key还是放那里,还是可以用来比较(但是不能做匹配操作)
但是如果频繁删除,符号表里会有很多“墓碑”,这不利于我们维护我们的符号表。因此我们不考虑这种方式。
2 删除的一般情况
由于二叉查找树的特殊结构,使得它的删除操作并没那么容易,我们还是采用递归的方式去做。很容易想到,删除操作可能会出三种情况:
2.1 被删除元素没有孩子
这个比较简单,直接返回null,就可以让它的父亲节点指向null,然后自己就可以等着被回收就好了。
2.2 被删除的元素有一个孩子
这个也还好,直接返回自己的另一个孩子,让自己的父亲节点指向自己的另一个孩子,自己坐等被回收。
情形1和2可以用来实现删除
最小值
或最大值
public void deleteMin() { root = deleteMin(root); } private Node deleteMin(Node x) { if (x.left == null) return x.right; x.left = deleteMin(x.left); x.count = 1 + size(x.left) + size(x.right); return x; } public void deleteMax() { root = deleteMax(root); } private Node deleteMax(Node x) { if (x.right == null) return x.left; x.right= deleteMin(x.right); x.count = 1 + size(x.left) + size(x.right); return x; }
2.3 被删除的元素有两个孩子
这个是最麻烦的操作,前使用的方案是50年前提出来的Hibbard deletion(50年了,天呐)
找自己
右孩子
里面的最小值(最左
)然后替换自己和它,然后删除自己
原理: root的右孩子肯定全大于左孩子,然后它又是右孩子里面的最小值,所以它做root节点可以满足左边比自己小,右边比自己大的条件。
注意:要同步更新count值
public void delete(Key key){ return delete(root,key);}private Node delete(Node x, Key key){ if(x == null) return null; /*********找key*************/ int cmp = key.compareTo(x.key); if(cmp > 0) x.right = delete(x.right,key); if(cmp < 0) x.left = delete(x.left,key); /**********找到key************/ else{ /**********情形1/2************/ if(x.right == null) return x.left; if(x.left == null) return x.right; /**********情形3***********/ Node min = Min(x.right); min.right = deleteMin(x.right); min.left = x.left; return min; } /**********更新count***********/ x.count = 1 + size(x.right) + size(x.left); }
3 问题
由于删除操作的特殊性,每次找右孩子替代自己,会导致二叉树失去平衡,大量随机测试表明,通过随机的删除后的二叉树深度会退化到
所以,看似简单的问题,却难有好的解决方案。
50年来二叉的树的删除仍然是一个研究方向,大量科学家在寻找一个更直观有效的删除策略。就像我们本能的觉得应该有更简单的in place
的归并策略,但是50年过去了,仍然没人发现。
- 《 常见算法与数据结构》符号表ST(4)——二叉查找树删除 (附动画)
- 《 常见算法与数据结构》符号表ST(3)——二叉查找树 (附动画)
- 《 常见算法与数据结构》平衡查找树(2)——红黑树(附动画)
- 《 常见算法与数据结构》平衡查找树(1)—— 2-3查找树(附动画)
- 《 常见算法与数据结构》符号表ST(1)——基本介绍
- 《 常见算法与数据结构》符号表ST(2)——初等实现分析和有序符号表
- 《常见算法和数据结构》元素排序(1)——简单排序(附动画)
- 数据结构与算法分析--二叉排序树(二叉查找树,二叉搜索树)的查找、插入和删除操作
- 数据结构与算法分析(三) —— 二叉查找树的实现
- 二叉查找树——删除操作(算法导论)
- 数据结构与算法(C语言版)__二叉查找树
- 数据结构与算法-二叉查找树(java描述)
- 数据结构与算法4:二叉树1(二叉查找树)
- Javascript数据结构算法之二叉查找树BST(构造,遍历,查找,删除,计数)
- 数据结构与算法(十三)删除二叉树结点
- 【数据结构与算法】二叉树递归与非递归遍历(附完整源码)
- 【数据结构与算法】二叉树递归与非递归遍历(附完整源码)
- 【数据结构与算法】二叉树递归与非递归遍历(附完整源码)
- 联发科Linkit 7688 DUO(三): 通过 Arduino 控制外设和传感器
- ios开发UI系列之使用AutoLayout的几个经典的布局技巧
- Spring MVC 概述
- C++primer知识点(二)
- Android 常用Adapter(ArrayAdapter ,SimpleAdapter ,BaseAdapter )的具体用法
- 《 常见算法与数据结构》符号表ST(4)——二叉查找树删除 (附动画)
- 聊聊同步、异步、阻塞与非阻塞
- 基于OpenCV的火焰检测(一)——图像预处理
- C++primer知识点(三)
- 深入理解JVM03--垃圾收集算法(“标记-清除”,“复制”,“标记-整理”,“分代收集”)
- Java多线程和并发基础面试问答
- 2016"百度之星" - 资格赛(Astar Round1)Problem C
- strcmp 函数
- 重载赋值运算符--引用计数