二叉搜索树基本操作

1.二叉搜索树概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

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

2.插入元素

思路

首先应该找到合适的位置,如果发现插入的元素重复了,就插入失败,返回false,插入成功返回true。
(只能插入尾部,不能插入到中间)

代码
    //插入
    public boolean insert(int key){
        if (root == null){
            //当前为空树,直接让root指向key对应的节点即可
            root = new Node(key);
            return true;
        }
        //需要先找到合适的位置
        Node cur = root;
        Node parent = null;//parent始终指向cur的父节点
        while (cur != null){
            if (key < cur.key){
                parent = cur;
                cur = cur.left;
            }else if (key > cur.key){
                parent = cur;
                cur = cur.right;
            }else {
                //插入失败
                return false;
            }
        }
        //循环结束的时候,cur就指向了null,当前元素就要插入到parent的子树位置上
        if (key < parent.key){
            //插入到 parent 的左侧
            parent.left = new Node(key);
        }else {
            parent.right = new Node(key);
        }
        return true; 
    }

3.查找元素

思路

根据元素的位置进行查找,查找是否存在,如果存在就返回对应的值。

代码
  //查找
    public Node find(int key){
        //查找key是否存在,如果存在就返回对应的Node
        Node cur = root;
        while (cur != null){
            if (key < cur.key){
                //就去左子树中找
                cur = cur.left;
            }else if (key > cur.key){
                //就去右子树中找
                cur = cur.right;
            }else {
                //相等就是找到了
                return cur;
            }
        }
        //循环结束了也没找到
        return null;
    }

4.删除元素

思路

需要考虑不同的情况:

1)待删除元素是父节点的左子树
待删除元素的左子树为空,右子树非空
在这里插入图片描述

2)待删除元素是父节点的右子树
待删除元素的左子树为空,右子树非空
在这里插入图片描述

3)待删除元素是父节点的左子树
左子树非空,右子树为空
在这里插入图片描述

4)待删除元素是父节点的右子树
带删除元素的左子树非空,右子树为空
在这里插入图片描述
5)待删除元素是父节点的左子树(右子树)
待删除元素的左右子树都非空

解决方法:找待删除元素右子树中的最小,或者也可以找左子树中的最大
在这里插入图片描述

代码
  //删除
    //指定值进行删除,删除成功返回true,删除失败返回false
    //key在树中存在,就删除成功
    //key在树中不存在,就删除失败
    public boolean remove(int key){
        //先找到要删除的节点的位置,在进行具体的删除
        //找到这个待删除元素,再去判定是哪种情况
        Node cur = root;
        Node parent = null;
        while (cur != null){
            if (key < cur.key){
                parent = cur;
                cur = cur.left;
            }else if (key > cur.key){
                parent = cur;
                cur = cur.right;
            }else {
                //找到了
                //在这个方法中判定是哪一种情况,
                removeNode(parent,cur);
                return true;
            }
        }
        return false;
    }

    private void removeNode(Node parent, Node cur) {
        if (cur.left == null){
            //1.要删除的元素没有左子树
            if (cur == root){
                //1.1如果要删除节点为root
                root = cur.right;
            }else if (cur == parent.left){
                //1.2 对应情况1)
                parent.left = cur.right;
            }else {
                //1.3对应情况2)
                parent.right = cur.right;
            }
        }else if (cur.right == null){
            //2.要删除的元素没有右子树
            if (cur == root){
                //2.1 如果要删除节点为root
                root = cur.left;
            }else if (cur == parent.left){
                //2.2 对应情况3)
                parent.left = cur.left;
            }else {
                //2.3 对应情况4)
                parent.right = cur.left;
            }
        }else {
            //当前要删除节点有两个子树,对应的情况5)
            //1.先找到 右子树中最小的元素(替罪羊)
            Node goatParent = cur;
            Node scapeGoat = cur.right;
            while (scapeGoat.left != null){
                goatParent = scapeGoat.left;
                scapeGoat = scapeGoat.left;
            }
            //循环结束的时候,就已经找到了最小值
            //2.把刚才找到的元素的值赋给待删除元素
            cur.key = scapeGoat.key;
            //3.删除替罪羊节点
            //替罪羊没有左子树,和情况1)和2)一样
            if (scapeGoat == goatParent.left){
                goatParent.left = scapeGoat.right;
            }else {
                goatParent.right = scapeGoat.right;
            }
        }
    }

5.验证结果

由于需要验证,就需要用先序遍历和中序遍历来验证是否为二叉搜索树


    public void preOrder(Node root){
        if (root == null){
            return;
        }
        System.out.print(root.key +" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    public void inOrder(Node root){
        if (root == null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.key +" ");
        inOrder(root.right);
    }


    public static void main(String[] args) {
        BinarySearchTree tree = new BinarySearchTree();
        tree.insert(9);
        tree.insert(5);
        tree.insert(2);
        tree.insert(7);
        tree.insert(3);
        tree.insert(6);
        tree.insert(8);

        //打印先序遍历和中序遍历
        tree.preOrder(tree.root);
        System.out.println();
        tree.inOrder(tree.root);

    }

输出结果
在这里插入图片描述
二叉搜索树为
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
二叉排序树也称为二叉搜索树,它是一种特殊的二叉树,满足以下性质: 1. 左子树中的所有节点的值均小于根节点的值; 2. 右子树中的所有节点的值均大于根节点的值; 3. 左子树和右子树也都是二叉排序树。 基本操作包括插入节点、删除节点和查找节点。下面是它们的实现: 1. 插入节点: 插入节点操作用于向二叉排序树中插入一个新节点。从根节点开始,比较插入节点的值与当前节点的值,如果小于当前节点的值,则进入左子树,否则进入右子树。直到找到一个空位置,将新节点插入到该位置。 示例代码如下: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None def insert_node(root, val): if root is None: return TreeNode(val) if val < root.val: root.left = insert_node(root.left, val) else: root.right = insert_node(root.right, val) return root ``` 2. 删除节点: 删除节点操作用于从二叉排序树中删除指定节点。分为三种情况: - 被删除节点没有子节点:直接删除即可; - 被删除节点只有一个子节点:将子节点替代被删除节点的位置; - 被删除节点有两个子节点:找到被删除节点的后继节点(右子树中最小的节点),将后继节点的值复制到被删除节点,然后删除后继节点。 示例代码如下: ```python def find_min(node): while node.left is not None: node = node.left return node def delete_node(root, val): if root is None: return root if val < root.val: root.left = delete_node(root.left, val) elif val > root.val: root.right = delete_node(root.right, val) else: if root.left is None: return root.right elif root.right is None: return root.left else: successor = find_min(root.right) root.val = successor.val root.right = delete_node(root.right, successor.val) return root ``` 3. 查找节点: 查找节点操作用于在二叉排序树中查找指定值的节点。从根节点开始,比较目标值与当前节点的值,如果小于当前节点的值,则进入左子树,否则进入右子树。如果找到匹配的节点,则返回该节点;如果遍历完整个树仍未找到匹配的节点,则返回空。 示例代码如下: ```python def search_node(root, val): if root is None or root.val == val: return root if val < root.val: return search_node(root.left, val) else: return search_node(root.right, val) ``` 以上是二叉排序树基本操作的实现。你可以根据需要调用这些函数来操作二叉排序树。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值