搜索树

本文介绍了二叉搜索树的基础概念,包括其定义和特性。二叉搜索树保证了中序遍历的结果是有序的,并且不允许重复的Key值。接着详细阐述了在搜索树中查找、插入和删除操作的具体步骤和逻辑,特别是删除操作时,针对不同情况(如无左子树、无右子树和左右子树皆有)给出了相应的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搜索树

基础概念

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

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树
  • 搜索树中序遍历是有序的。
  • 搜索树是纯Key模型,Key值不允许有重复的。
    在这里插入图片描述
查找
 public static  class Node{
        int key;
        Node left;
        Node right;
        public Node(int key){
            this.key=key;
        }
    }
    private Node root=null;

在搜索树中查找key,找到返回key所在的结点,找不到返回null

public Node search(int key){
       Node pre=root;
       while(pre!=null){
           if(key==pre.key){
               return pre;
           }else if(key<pre.key){
               pre=pre.left;
           }else{
               pre=pre.right;
           }
       }
       return null;
    }

插入

插入成功返回true,插入失败返回false, 搜索树不允许key重复,所以遇到key相等直接返回false。如果根结点为null 则直接插入,否则先找到合适的父母结点再插入key值,

public boolean insert(int key){
       if(root==null){
           root=new Node(key);
           return true;
       }
       Node pre=root;
       Node parent=null;
       while(pre!=null){
           if(key==pre.key){
               return false;
           }else if(key<pre.key){
               parent=pre;
               pre=pre.left;
           }else{
               parent=pre;
               pre=pre.right;
           }
       }
       Node node=new Node(key);
       if(key<parent.key){
           parent.left=node;
       }else{
           parent.right=node;
       }
       return true;
    }
删除

设待删除结点为 cur, 待删除结点的双亲结点为 parent

  1. cur.left == null
    cur 是 root,则 root = cur.right
    cur 不是 root,cur 是 parent.left,则 parent.left = cur.right
    cur 不是 root,cur 是 parent.right,则 parent.right = cur.right
  2. cur.right == null
    cur 是 root,则 root = cur.left
    cur 不是 root,cur 是 parent.left,则 parent.left = cur.left
    cur 不是 root,cur 是 parent.right,则 parent.right = cur.left
  3. cur.left != null && cur.right != null
    需要使用替换法进行删除,即在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题(即查找左子树做大的或者右子树最小的来替换)
public  boolean remove(int key){
        Node cur=root;
        Node parent=null;
        while(cur!=null){
            if(key==cur.key){
                removeNode(parent,cur);
                return true;
            }else if(key<cur.key){
                parent=cur;
                cur=cur.left;
            }else{
                parent=cur;
                cur=cur.right;
            }
        }
        return false;
    }
    public void removeNode(Node parent,Node 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{
            Node goatparent=cur;
            Node goat=cur.right;
            while(goat.left!=null){
                goatparent=goat;
                goat=goat.left;
            }
            cur.key=goat.key;
            if(goat==goatparent.left){
                goatparent.left=goat.right;
            }else{
                goatparent .right=goat.right;
            }
        }
    }
测试
 public static void main(String[] args) {
        // 1. 创建搜索树
        // 2. 随机插入一些数据
        // 3. 打印前序 + 中序遍历
        // 4. 查找
        Text1 tree = new Text1();
        int[] keys = { 3, 9, 7, 4, 1, 6, 2, 8, 5 };
        for (int key : keys) {
            System.out.println(tree.insert(key));
        }
        System.out.println("插入重复数据");
        System.out.println(tree.insert(7));

        System.out.println("前序遍历");
        preOrder(tree.root);
        System.out.println("中序遍历");
        inOrder(tree.root);

        System.out.println(tree.search(7).key);
        System.out.println(tree.search(8).key);
        System.out.println(tree.search(5).key);
    }

    private static void inOrder(Node node) {
        if (node != null) {
            inOrder(node.left);
            System.out.println(node.key);
            inOrder(node.right);
        }
    }

    private static void preOrder(Node node) {
        if (node != null) {
            System.out.println(node.key);
            preOrder(node.left);
            preOrder(node.right);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值