二叉搜索树【Java数据结构】
目录
搜索树
1.概念
2. 操作-查找
3. 操作-插入
4. 操作-删除
5. 代码实现
搜索树
1.概念
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值若它的右子树不为空,则右子树上所有节点的值都大于根节点的值它的左右子树也分别为二叉搜索树
2. 操作-查找
查找规律:
若根节点不为空:
如果根节点val = 查找val,返回true
如果根节点val > 查找val,从该节点左子树查找
如果根节点val < 查找val,从该节点右子树查找
若最后根节点为空,返回false
3. 操作-插入
1.如果树为空树,即根为null,就可以直接插入。
2.如果树非空树,应按照查找逻辑找到插入位置,插入新节点。
通过查找的规则来寻找插入节点,每次插入的节点都为叶子节点!
注意相同的key是不可以插入的!
从根节点开始,根据查找的规则用cur进行节点遍历,同时用prev来存储遍历的前一个节点,直到cur == null时,此时prev已经遍历到叶子节点,再进行判断key与该叶子节点的大小关系来决定放在left还是right。
4. 操作-删除
设待删除结点为 cur, 待删除结点的双亲结点为 parent
分为三种情况:
1. cur.left == null2. cur.right == null3. cur.left != null && cur.right != null
1. cur.left == null
1. cur 是 root,则 root = cur.right
2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.right
3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.right
2. cur.right == null
1. cur 是 root,则 root = cur.left
2. cur 不是 root,cur 是 parent.left,则 parent.left = cur.left
3. cur 不是 root,cur 是 parent.right,则 parent.right = cur.left
3. cur.left != null && cur.right != null
对于这一种情况,我们采用替罪羊的方式进行删除,即寻找要删除节点的左子树的最右端的一个节点,该节点的val为左子树的最大值,同时也满足小于要删除节点的右子树的所有节点,用该值填补到被删除节点,所以问题就转变为:处理这个替换节点原位置的删除问题了。而这个替换节点作为左子树的最右端,它的 right 为 null ,所以就是上述cur.right == null这一种情况了,问题也就迎刃而解了。
或者寻找要删除节点的右子树的最左端的一个节点(中序下的第一个结点),该节点的val为右子树的最小值,同时也满足大于要删除节点的左子树的所有节点。用该值填补到被被删除节点,再处理这个替换节点原位置的删除问题了。这个替换节点作为右子树的最左端,它的 left 为 null ,也就是上述cur.left == null这一种情况了。
如删除上图的cur,可以采用以下两种方式。
易错点!!!
此时,还有一种特殊情况需要注意,以右树最左节点为例:tmp=cur.right
在上述的讨论情况中,到最后删除替换节点原位置这一阶段时,我们采用parent.left = tmp.right的方法,如下图情况一。
但此时我们忽略了另一种情况:一开始的接收到的tmp就已经是右子树的最左端了,如下图情况二。此时要删除替换节点原位置的时候,就不可以再用parent.left = tmp.right这条语句了!!!而应该用parent.right = tmp.right。
所以再完成代码的时候应该添加判断语句parent.right == tmp,成立实现情况二,不成立实现情况一。(结合下面代码分析效果更佳)
5. 代码实现
class BinarySearchTree{static class TreeNode{public int val;public TreeNode left;public TreeNode right;public TreeNode(int val){this.val = val;}}public TreeNode root = null;/*** 查找一个val 是不是在当前的搜索树当中* @param val* @return 有返回 没有返回null*/public boolean search(int val){TreeNode cur = root;while (cur != null){if (cur.val<val){cur = cur.right;} else if (cur.val>val) {cur = cur.left;}else{return true;}}return false;}//中序遍历public void inorder(TreeNode root){if (root == null){return;}inorder(root.left);System.out.print(root.val+" ");inorder(root.right);}/*** 插入元素key* @param key* @return* 每次插入都是插入在叶子结点!!!!*/public boolean insert(int key){if (root == null){root = new TreeNode(key);return true;}TreeNode cur = root;TreeNode prev = null;while (cur!=null){if (cur.val>key){prev = cur;cur = cur.left;}else if (cur.val<key){prev = cur;cur = cur.right;}else {return false; //相同的key是不能进行插入的}}//cur = null 了//判断key大于prev还是小于prev来判断在左边还是右边TreeNode newNode = new TreeNode(key);if (key> prev.val){prev.right = newNode;}else{prev.left = newNode;}return true;}public void remove(int key){TreeNode cur = root;TreeNode prev = null;while (cur!=null){if (key> cur.val){prev = cur;cur = cur.right;} else if (key< cur.val) {prev = cur;cur = cur.left;}else {removeNode(cur,prev);return;}}}public void removeNode(TreeNode cur,TreeNode prev){if (cur.left == null){ //该节点左边为nullif (cur == root){ //该节点为根结点root = cur.right;} else if (cur == prev.left) { //该节点为prev的左边prev.left = cur.right;}else { //该节点为prev的右边prev.right = cur.right;}} else if (cur.right == null) { //该节点右边为nullif (cur == root){root = cur.left;} else if (cur == prev.left) {prev.left = cur.left;}else {prev.right = cur.left;}}else{ //该节点左右两边都不为nullTreeNode tmp = cur.right; //找到左树最右节点或者右树最左节点来作为删除节点的值,然后操作删除左树最右节点或者右树最左节点。一般以右树最左节点来计算TreeNode tmpParent = cur;while (tmp.left!=null){tmpParent = tmp;tmp = tmp.left; //找到右树最左节点后,剩下的操作就是将该节点值赋给删除的节点,然后操作删除右树的最左节点}cur.val = tmp.val;if (tmpParent.right == tmp){tmpParent.right = tmp.right; //一开始的tmp就已经是右树最左端了!!!}else {tmpParent.left = tmp.right; //非一开始的tmp就已经是右树最左端了!!!}}}}
二叉搜索树【Java数据结构】相关推荐
- 《LeetCode力扣练习》第96题 不同的二叉搜索树 Java
<LeetCode力扣练习>第96题 不同的二叉搜索树 Java 一.资源 题目: 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回 ...
- Leetcode--96. 不同的二叉搜索树(java)
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 ...
- 使用C++实现二叉搜索树的数据结构
需要注意的地方: ①二叉搜索树删除一个指定结点R,若R为叶子结点,则将R的父结点中指向R的指针改为指向nullptr:若R的左右子结点一个为空,一个非空,则将R的父结点中指向R的指针改为指向R的非空子 ...
- 二叉搜索树 【数据结构】
二叉搜索树 概念 特点 基本操作 1.插入元素 2.查找元素 3.删除元素 概念 二叉搜索树是一种特殊的二叉树 特点 左子树中的值都小于根节点,右子树中的值都大于根节点 故:中序遍历结果就会得到一个有 ...
- java 二叉查找树_如何在Java中实现二叉搜索树( binary search tree)?
二叉搜索树或BST是一种流行的数据结构,用于保持元素的顺序.二叉搜索树是二叉树,其中左子节点的值小于或等于父节点,右子节点的值大于或等于父节点.由于它是二叉树,它只能有0,1或2个子节点.二叉搜索树之 ...
- 【算法】有序链表转换二叉搜索树和从中序与后序遍历序列构造二叉树Java解答参考
三道算法题 1.有序链表转换二叉搜索树 Java代码参考 2.从中序与后序遍历序列构造二叉树 Java代码参考 3.移除元素 Java代码参考 1.有序链表转换二叉搜索树 给定一个单链表,其中的元素按 ...
- 剑指offer | 面试题54:二叉搜索树的第k大节点
转载本文章请标明作者和出处 本文出自<Darwin的程序空间> 本文题目和部分解题思路来源自<剑指offer>第二版 开始行动,你已经成功一半了,献给正在奋斗的我们 题目 给定 ...
- 二叉搜索树简介和部分题目
引言 二叉搜索树是一个有序树,遵循以下规则: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉 ...
- 有序链表转换二叉搜索树(LeetCode)
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10,-3,0, ...
- c++实现二叉搜索树
自己实现了一下二叉搜索树的数据结构.记录一下: #include <iostream>using namespace std;struct TreeNode{int val;TreeNod ...
最新文章
- 2017年12月英语四级翻译预测
- go语言json解析的坑 注意事项
- 第二十二章 面向对象
- shared_ptr简介以及常见问题
- 前端学习(2325):angular之添加新组件
- Python reload() 函数
- C++编程(一):匈牙利命名法
- php是走什么协议,TCP是什么协议
- 《Spark The Definitive Guide》Chapter 6:处理不同类型的数据
- PCA(Principal Component Analysis)原理简单分析
- (135)FPGA面试题-介绍FPGA的速度等级与温度等级
- 【医疗影像处理】去除医疗影像中背景的影响2D/3D【numpy-code】
- android10LTE,Jelly 2:全球最小的Android 10 4G智能手机
- python情感分析词典_基于情感词典的文本情感分析
- MySQL的存储函数与存储过程的区别
- Stm32串口通信基础实验
- 抽奖活动软件 html,webAPP最常用的活动促销案例:大转盘H5抽奖特效
- 用JS代码输出101-200之间的素数
- python scrapy框架 抓取的图片路径打不开图片_Python使用Scrapy爬虫框架全站爬取图片并保存本地的实现代码...
- HTML基础选择器之属性选择器的基本介绍
热门文章
- 自定义Camera系列之:TextureView + Camera
- 丘仕达工作前给大家的礼物(转)
- MySQL自带数据库
- 【调剂】江西科技师范大学电子科学与技术接收调剂研究生
- 奖券数目c语言答案,2015 年蓝桥杯 C 语言 B 组省赛第 1 题: 奖券数目 (四种解法 + 详细分析)...
- 物理真机上LUKS结合TPM的测试 —— 使用自己生成的密钥(问题版)
- 贾跃亭创办的FF又有新动作:国内成立新公司
- 最佳iOS设备管理器imazing 2.16.9官网Mac/Windows下载电脑版怎么下载安装
- java页面字体设置颜色_java 设置字体颜色字体 窗体设置图片背景
- sources和binaries文件区别