作者:渴望力量的土狗
博客主页:渴望力量的土狗的博客主页
专栏:数据结构与算法
工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器——牛客网
目录
二叉搜索树是一种特殊的二叉树,要么是一颗空树,要么满足以下几点:
1、 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3、它的左右子树也分别为二叉搜索树
下面就是一颗典型的二叉搜索树:
二叉搜索树的查找效率是比较高的,类似与我们所熟知的二分查找。它的查找方式是这样的:如果我们要查找6这个数字,那么我们从根节点开始,遇到根节点的val是5,6>5,所以我们要往右搜寻,遇到7的时候,6<7,这时我们向右左找即可,这就找到了我们要找的数字。
我们可以看的出它的时间复杂度是O(logn),也就是搜索树的高度,但是,如果这颗搜索树呈现线性的化,也就是一条线的情况:

这时我们在搜索的时候就类似于线性查找,时间复杂度就达到了O(n)了。
然后就是二叉搜索树的插入操作,我们怎么把数据插入到原来的二叉搜索树当中呢?插入的操作和查找有点类似,需要搜索到需要查找的位置。具体逻辑为:当树空的时候直接new一个结点即可,不空的情况下,当我们要插入一个元素的时候我们需要知道它的前一个元素,这样我们才能实现插入操作,插入的位置都是为空的,所以我们要查找到它适合的位置即可。
二叉搜索树的删除属于最重要的内容,因为它的删除操作可能比较复杂一点,我们在删除某一个结点的时候需要调整,你怎么知道调整后是什么样子的呢?删除前我们还是要进行搜索,找到待删除结点的位置。
这里先说一下删除的步骤:
设待删除结点为 cur, 待删除结点的双亲结点为 parent
一. 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
二. 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
三. cur.left != null && cur.right != null
1. 需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被 删除节点中,再来处理该结点的删除问题
下面对二叉搜索树进行实现:
- public class BinarySearchTree {
-
- static class TreeNode {
- public int key;
- public TreeNode left;
- public TreeNode right;
-
- TreeNode(int key) {
- this.key = key;
- }
- }
-
- public TreeNode root;
-
- /**
- * 插入一个元素
- * @param key
- */
- public boolean insert(int key) {
- //根结点
- if(root==null){
- root=new TreeNode(key);
- return true;
- }
-
- //找到需要插入的位置
- TreeNode cur=root;//找位置
- TreeNode parent=cur;//插入位置的父节点
- while(cur!=null){
- if(cur.key
- parent=cur;
- cur=cur.right;
- } else if (cur.key>key) {
- parent=cur;
- cur=cur.left;
- }else{
- //不可以插入相同的元素
- return false;
- }
- }
- //此时cur为空了,这个位置就是插入的位置
- //这里需要讨论插入到parent的左边还是右边
- if(key> parent.key){
- //插入右边
- parent.right=new TreeNode(key);
- }else{
- //插入左边
- parent.left=new TreeNode(key);
- }
- return true;
- }
-
- /**
- * 查找key是否存在
- * @param key
- * @return
- */
- public TreeNode search(int key) {
- TreeNode cur=root;
-
- //我们搜索的最差情况为当前结点为空
- while (cur!=null){
-
- //先判断根结点
- if(cur.key==key){
- return cur;
- //如果key比结点的key大向右找
- } else if (cur.key
- cur=cur.right;
- //如果key比结点的key小向左找
- } else {
-
- cur=cur.left;
- }
- }
- //如果cur为空则返回空
- return null;
- }
- //中序遍历
- public void inOrder(TreeNode root){
-
- if(root==null){
- return;
- }
- inOrder(root.left);
- System.out.print(root.key+" ");
- inOrder(root.right);
-
-
- }
-
-
- /**
- * 删除key的值
- * @param key
- * @return
- */
- public void remove(int key) {
-
- TreeNode parent = null;
- TreeNode cur = root;
- while (cur != null) {
- if(cur.key == key) {
- removeNode(parent,cur);
- return;
- }else if(cur.key < key) {
- parent = cur;
- cur = cur.right;
- }else {
- parent = cur;
- cur = cur.left;
- }
- }
- }
-
- private void removeNode(TreeNode parent,TreeNode cur) {
- if(cur.left == null) {
- if(cur == root) {
- root = cur.right;
- }else if(cur == parent.left) {
- parent.left = cur.right;
- }else {
- parent.right = cur.right;
- }
- }else if(cur.right == null) {
- if(cur == root) {
- root = cur.left;
- } else if (cur == parent.left) {
- parent.left = cur.left;
- }else {
- parent.right = cur.left;
- }
- }else {
- TreeNode target = cur.right;
- TreeNode targetParent = cur;
- while (target.left != null) {
- targetParent = target;
- target = target.left;
- }
- cur.key = target.key;
- if(target == targetParent.left) {
- targetParent.left = target.right;
- }else {
- targetParent.right = target.right;
- }
- }
- }
-
-
- }
-
相关阅读:
linux安装jenkins
vulnhub靶机raven2
云原生之使用Docker部署Laverna笔记工具
vue3+TS实战中Dialog弹窗封装复用技巧(修改和添加共用一个弹窗)涉及组件的传值(defineProps)和组件的自定义事件(emits)
CCF开源发展委员会正式成立,探索开源发展新途径
初识Python——Python环境安装配置
【【萌新的SOC大学习之hello_world】】
第10章 MySQL(一)
build g2o viewer on macos
并发与并行,同步和异步,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang并发编程之GoroutineEP13
-
原文地址:https://blog.csdn.net/m0_67995737/article/details/127415972