【数据结构】二叉搜索树

目录

二叉搜索树

二叉搜索树不是空树就包含以下性质:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
  • 它的左右子树也分别为二叉搜索树。

也就是说根节点左边比根节点小右边比根节点大。

二叉搜索树的模拟实现

一般实现的二叉搜索树中都不含有相同值的节点。

接口实现

实现的接口(成员方法)如下:

java 复制代码
public class BinarySearchTree {
    // 插入一个元素
    public boolean insert(int key) {}
    //查找key是否存在
    public TreeNode search(int key) {}
    //删除key的值
    public boolean remove(int key) {}
}

成员变量

我们使用内部类来表示二叉树的每一个节点。并定义出来根节点。

java 复制代码
static class TreeNode {
        public int key;
        public TreeNode left;
        public TreeNode right;
        TreeNode(int key) {
            this.key = key;
        }
    }
    public TreeNode root;

插入一个元素

逻辑就是插入一个元素总能在空节点位置找到该插入的位置。

就是下图中由黑线连接的空节点。

实现思路:

  1. 如果当前树为空则插入节点为根节点。
  2. 依次向下找到该插入的位置,同时要获得该位置的父亲节点。
  3. 最后插入。

注意:**一般实现的二叉搜索树中都不含有相同值的节点。**所以插入已有元素是不会成功的。

java 复制代码
	// 插入一个元素
	public boolean insert(int key) {
        TreeNode node = new TreeNode(key);
        if(root == null) root = node;
        TreeNode pre = null;
        TreeNode cur = root;
        
        while (cur != null){
            if(cur.key == key) {
                return false;
            } else if(cur.key > key) {
                pre = cur;
                cur = cur.left;
            } else {
                pre = cur;
                cur = cur.right;
            }
        }
        if(pre.key > key) pre.left = node;
        if(pre.key < key) pre.right = node;
        return true;
    }

查找key是否存在

逻辑与二分查找类似。

代码实现思路:

  1. 当前节点等于key,返回当前节点。
  2. 当前节点比key大就去左子树找。
  3. 当前节点比key小就去右子树找。
  4. 都没找到返回空。
java 复制代码
//查找key是否存在
    public TreeNode search(int key) {
        TreeNode cur = root;
        while(cur != null) {
            if(cur.key == key) return cur;
            if(cur.key < key) cur = cur.right;
            if(cur.key > key) cur = cur.left;
        }
        return null;
    }

查询分析:

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:logN。

最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N / 2。

删除key的值

实现思路:

  1. 设待删除结点为 cur, 待删除结点的双亲结点为 pre。

  2. 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。

  3. 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。

  4. cur.left != null && cur.right != null:

    两个思路:在左子树找最大值进行替换,右子树找最小值进行替换。

java 复制代码
//删除key的值
    public boolean remove(int key) {
        TreeNode node = new TreeNode(key);
        if(root == null) throw new NullPointerException();
        TreeNode pre = null;
        TreeNode cur = root;

        while (cur != null){
            if(cur.key == key) {
                removeNode(cur,pre);
                return true;
            } else if(cur.key > key) {
                pre = cur;
                cur = cur.left;
            } else {
                pre = cur;
                cur = cur.right;
            }
        }
        return false;
    }

    private void removeNode(TreeNode cur, TreeNode pre) {
        if(cur.left == null) {
          if(cur == root) {
              root = cur.right;
          } else if(cur == pre.right) {
              pre.right = cur.right;
          } else {
              pre.left = cur.right;
          }
        } else if(cur.right == null) {
            if(cur == root) {
                root = cur.left;
            } else if(cur == pre.right) {
                pre.right = cur.left;
            } else {
                pre.left = cur.left;
            }
        } else {
            //找到右树最小值替换
            TreeNode target = cur;
            pre =  cur;
           cur = cur.right;
           while (cur.left != null) {
               pre = cur;
               cur = cur.left;
           }
           //排除待删除节点左子树为空
           if(pre.right == cur) {
               pre = cur;
               return;
           }
           target.key = cur.key;
           cur = null;
        }
    }

TreeMap 和 TreeSet 即 java 中利用搜索树实现的 Map 和 Set;实际上用的是红黑树,而红黑树是一棵近似平衡的二叉搜索树,即在二叉搜索树的基础之上 + 颜色以及红黑树性质验证。

练习

二叉搜索树与双向链表

题目描述:

题解

解题思路:

要有一个前驱pre节点。 递归到上一级的时候 当前的根节点(pRootOfTree)就是pre的后继。

按中序遍历来遍历二叉搜索树即可。

java 复制代码
public class Solution {
    TreeNode pre = null;
    TreeNode head = null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree ==null) return null;
        Convert(pRootOfTree.left);
        if(head == null) {
            head = pRootOfTree;
        }
        if(pre != null) {
            pRootOfTree.left=pre;
            pre.right=pRootOfTree;
        }
        pre=pRootOfTree;
        Convert(pRootOfTree.right);
        return head;
    }
}
相关推荐
天上掉下来个程小白3 分钟前
开发环境搭建-06.后端环境搭建-前后端联调-Nginx反向代理和负载均衡概念
java·运维·spring boot·后端·nginx·负载均衡·苍穹外卖
试着生存6 分钟前
java根据List<Object>中的某个属性排序(数据极少,顺序固定)
java·python·list
_星辰大海乀7 分钟前
LinkedList 双向链表
java·数据结构·链表·list·idea
小韩学长yyds18 分钟前
Java调用第三方HTTP接口:从入门到实战
java·开发语言·http
苏十八20 分钟前
JavaEE Servlet02
java·服务器·网络·java-ee·json
爬菜25 分钟前
异常(5)
java
苹果酱05671 小时前
Golang的数据库备份与恢复
java·vue.js·spring boot·mysql·课程设计
星空露珠1 小时前
迷你世界脚本显示板管理接口:DisPlayBoard
数据结构·游戏·lua
青石路1 小时前
经由同个文件多次压缩的文件MD5都不一样问题排查,感慨AI的强大!
java·后端
木头没有瓜1 小时前
Mybatis集合嵌套查询,三级嵌套
java·tomcat·mybatis