BST内部方法的实现
目录
(1)自定义输出
(2)插入操作add()
(3)判断该BST中是否存在值为val的元素——contains(int val)
(4)查找并返回BST中的最小/最大值——findMin/findMax
(5)删除最小/最大值并返回删除的该值——removeMin/removeMax
(6)删除值为val的元素——removeVal(int val)
(7)修改元素值
(1)自定义输出
- 按照先序遍历的顺序输出;
- 唯一不同的是,这里为便于更好的根据输出结果还原二叉树,我们引入用 “--” 连接的分隔符以示节点所在层次,下一层的高度比上一层的“--”长;
如下图,左侧结果即为右图BST的输出形式
代码实现
// 按先序遍历顺序输出各节点的值public String toString(){StringBuilder s = new StringBuilder();generateString(root,0,s);return s.toString();}private void generateString(TreeNode root, int height, StringBuilder s) {if(root == null){s.append(height(height)).append("Null\n");return;}
// root不为空,先拼接该根节点s.append(height(height)).append(root.val).append("\n");
// 递归左子树generateString(root.left,height + 1,s);
// 递归右子树generateString(root.right,height + 1,s);}/*** 输出高度为height的分割线长度* @param height* @return*/private String height(int height){StringBuilder s = new StringBuilder();for (int i = 0; i < height; i++) {s.append("--");}return s.toString();}
(2)插入操作add()
使插入后仍保持为二分搜索树
- 可以发现,待插入的新节点最后一定是插入在了叶子节点位置;
- 借助递归,通过判断根节点与待插入值的大小,递归插入左子树或右子树,直至走到某个子树最后
// 向BST中插入值为val的元素元素public void add(int val) {root = add(root, val);}/*** 递归,在以node为根节点的BST中插入值为val的元素** @param node* @param val* @return 新的根节点*/public TreeNode add(TreeNode node, int val) {
// 如果为空树,则插入值即为根节点if (node == null) {TreeNode newNode = new TreeNode(val);return newNode;}
// 如果值小,向左子树中插入if (val < node.val) {node.left = add(node.left, val);}
// 如果值大,向右子树中插入if (val > node.val) {node.right = add(node.right, val);}return node;}
(3)判断该BST中是否存在值为val的元素——contains(int val)
如果一节点的值 == val,说明能找到,返回true;
否则:
- 如果节点值 > val ,去该节点的左子树中找;
- 如果节点值 < val,去该节点的右子树中找;
一直走到某节点为空,仍然找不到,说明无该节点,返回false;
public boolean contains(int val) {return containsRecursion(root,val);}// 还是要递归实现public boolean containsRecursion(TreeNode root, int val) {if (root == null) {return false;}if (root.val == val) {return true;} else if (root.val > val) {return containsRecursion(root.left, val);} else {return containsRecursion(root.right,val);}}
(4)查找并返回BST中的最小/最大值——findMin/findMax
以找最小值为例:
最小值一定是左子树的最左节点;
所以,一直向左走,直到找到某节点不再有左节点
/*** 查找BST中的最小值* @return*/public int findMin(){
// 记得先判空if(size == 0){throw new NoSuchElementException("BST is empty! cannot find");}TreeNode min = minRecursion(root);return min.val;}// 递归实现,最小值就是左子树的最左节点,这里返回值为TreeNode是方便后续删除最小值时也可直接调用该方法private TreeNode minRecursion(TreeNode node){if(node.left == null){return node;}return minRecursion(node.left);}/*** 查找最大值* @return*/public int findMax(){if(size == 0){throw new NoSuchElementException("BST is empty!!! cannot find");}TreeNode max = maxRecursion(root);return max.val;}// 递归实现,最大值就是右子树的最右节点private TreeNode maxRecursion(TreeNode node) {if(node.right == null){return node;}return maxRecursion(node.right);}
(5)删除最小/最大值并返回删除的该值——removeMin/removeMax
以删除最小值为例:
- 先找到最小值节点
- 首先该节点一定无左子树,现在只需分析该节点有无右子树:
- 如果该节点有右子树,只需将该节点删除后让该节点的根节点直接连接该右子树即可
- 如果该节点无右子树,则右子树为null,我们发现上一种情况的做法仍然适用,因为连接空子树也正好是结果
3.综上,删除待删除结点再将右子树连接即可
如下面这个示例:
代码实现:
/*** 删除最小值并返回该删除的值为多少** @return*/public int removeMin() {if(size == 0){throw new NoSuchElementException("BST is empty!!! cannot remove the min");}TreeNode min = minRecursion(root);root = removeMinRecursion(root);return min.val;}private TreeNode removeMinRecursion(TreeNode node) {// 说明node就是待删除节点if (node.left == null) {// 先存下右节点TreeNode right = node.right;
// 再删除待删除节点node.right = node = null;size--;
// 最后返回右子树,返回右子树就相当于根右子树直接相连return right;}
// 否则不是待删除节点,则递归左子树node.left = removeMinRecursion(node.left);return node;}/*** 删除最大值并返回该删除的值是多少* @return*/public int removeMax(){if(size == 0){throw new NoSuchElementException("BST is empty!!! cannot remove the max");}TreeNode max = maxRecursion(root);root = removeMaxRecursion(root);return max.val;}private TreeNode removeMaxRecursion(TreeNode node) {if(node.right == null){TreeNode left = node.left;node.right = node = null;size--;return left;}node.right = removeMaxRecursion(node.right);return node;}
(6)删除值为val的元素——removeVal(int val)
- 先找到值为val的元素
- 分析该元素的左右子节点情况判断如何删除连接
- 若该元素只有左节点无右节点,则直接拼接左节点即可;
- 若该元素只有右节点无左节点,则直接拼接右节点即可;
- 若该元素左右节点都有,则需要找该元素的前驱或后继顶替该节点位置
【前驱:比它小的最近的元素,在BST中,即为该元素左子树中最大的那个】
【后继:比它大的下一个元素,在BST中,即为该元素右子树中最小的那个】
以找前驱为例:
【注意!!!】
在拼接9时,注意(1)、(2)的先后顺序,一定要先拼接(1)再拼接(2),因为(1)左子树会先删除左子树的最大,故应该先处理,如若先拼接(2),则在进行操作(1)删除元素时,会把拼接的右也包含在内,会出错
代码实现:
/*** 删除值为val的值* @param val*/public void removeVal(int val){if(size == 0){throw new NoSuchElementException("BST is empty!!! cannot remove the val");}root = removeHelper(root,val);}private TreeNode removeHelper(TreeNode node,int val){if(node == null){throw new NoSuchElementException("BST is empty!!! cannot remove the val");}
// 如果node就是待删除元素if(node.val == val){
// 如果只有左子树没有右子树if(node.right == null){TreeNode left = node.left;node.left = node = null;size --;return left;}if(node.left == null){TreeNode right = node.right;node.right = node = null;size--;return right;}
// 此种情况左右子树都不为空
// 找前驱TreeNode pre = maxRecursion(node.left);
// 先连接左边的线,左=删除自身后的子树pre.left = removeMaxRecursion(node.left);
// 再连接右,右直接拼接右即可pre.right = node.right;
// 删除val节点node.right = node.left = node = null;return pre;}else if(node.val < val){node.right = removeHelper(node.right,val);return node;}else{node.left = removeHelper(node.left,val);return node;}}
(7)修改元素值
——BST中只能先删除该元素,再插入新元素实现,即调用上述删除和插入方法
public void changeVal(int val){removeVal(val);add(val);}
BST内部方法的实现相关推荐
- python运行mcmc为何老出错_python中mcmc方法的实现
MCMC方法在贝叶斯统计中运用很多,MIT发布的EMCEE是实现的比较好的.介绍页面在下面.源代码中examples里的代码可以帮助理解各种功能,特别是line.py 列出了最小二乘法,最大似然法和M ...
- jQuery 中 data 方法的实现原理
jQuery 中 data 方法的实现原理 前言:jQuery 作为前端使用最多最广泛的 JS 库,其源码每个 JSer 都应该研究一下.早就打算看却一直被各种事拖着,上次某公司面试时被问到 jQue ...
- python回调类_python 回调函数和回调方法的实现分析
回调与事件驱动 回调函数有比较重要的意义:它在是事件驱动的体现 我们试想一个场景,如果我们触发了某个事件,比如点击事件 那么只要给这个点击事件绑定一个或多个处理事件,也就是回调函数 我们就可以在点击事 ...
- scala 函数方法、函数方法的实现原理
文章目录 1. 函数&方法 2. 函数&方法的实现原理 1. 函数&方法 scala中方法是类的一部分,而函数是一个对象,可以赋值给一个变量.scala 中的方法跟 Jav ...
- sort排序方法的实现原理
sort 排序方法的实现原理 我们比较常用的是直接调用 JS的 sort方法,围绕原生 JS方法,并结合 V8排序的代码一起来分析,以便碰到类似的 JS排序问题时能够轻松应对. 在开始前请思考 ...
- DataList中的按钮触发事件的方法的实现
DataList中的按钮触发事件的方法的实现 1.要在CommandName中设定名字如: <asp:Button id="Button1" runat=&quo ...
- Java黑皮书课后题第10章:**10.23(实现String类)在Java库中提供了String类,给出你自己对下面方法的实现(将新类命名为MyString2)
**10.23(实现String类)在Java库中提供了String类,给出你自己对下面方法的实现(将新类命名为MyString2) 题目 简短的吐槽 代码:这里将类名改用Test23_MyStrin ...
- JavaScript中子类调用父类方法的实现
一.前言 最近在项目中,前端框架使用JavaScript面向对象编程,遇到了诸多问题,其中最典型的问题就是子类调用父类(super class)同名方法,也就是如C#中子类中调用父类函数base.** ...
- 一文介绍备机重建各种方法的实现机制
摘要:本文将介绍备机重建各种方法的实现机制,并结合应用场景分析,以及对新增参数的使用建议,以期获得最佳应用效果. 本文分享自华为云社区<先码再看,一文介绍备机重建各种方法的实现机制>,原文 ...
最新文章
- Docker Swarm集群搭建
- 汇编语言 将a段和b段中的数据依次相加,结果存放在c段中
- 计算机上机模拟试题答案,2016计算机二级上机模拟试题及答案
- java程序中my.ini_帮忙写个JAVA 读写ini配置文件小程序!!!!!
- 域对抗网络Domain adversarial neural network及其应用相关论文
- java spite截取_Java內功心法,行為型設計模式
- 计算机 画图软件 快捷键大全,教你完整版电脑CAD快捷键大全
- 第四十二章 SQL函数 DATEADD
- 大数据时代的背景下 校园安防管理软件平台发展变化
- python获取阿里巴巴国际站商家信息
- 智工教育:一消《技术实务》知识点整理
- 常用的UML建模详解
- 【Excel】如何使用RegexString正则表达式
- 梯度与边缘检测常用算子:Roberts、Prewitt、Sobel、LOG,Canny、Lapacian算子
- esp8266烧录Html文件
- 附近的人打招呼V1.0
- 算法:单圈绝对值编码器处理成多圈的
- 六度空间-用图进行BFS遍历
- matlab deployment project做什么用的,Project是什么软件?BIM项目管理的必备软件之Project,它的功能和作用你看看就知道了...
- Stevey's Google Platforms Rant