二叉排序树的插入删除和查找(数据结构实训)(难度系数100)

二叉排序树的插入删除和查找

pre: 前序遍历
in: 中序遍历
post:后序遍历
insert: 插入,本题中不会出现相同的元素
delete: 删除,删除成功输出TRUE,没有该元素则输出FALSE,删除的方法是如果有左子树,以左子树中最大值作为新的树根,否则,以右子树最小值作为树根。
search: 查找,存在该元素输出YES, 否则输出NO
exit:退出
输入:
输入的第一行为整数 N
接下来一行为N个整数,你需要把这N个整数构建出相应的二叉排序树
之后是一组指令。

输出:
根据相应的指令进行输出。说明:遍历各元素之间用一个空格隔开。

样例输入:
10
31 15 9 5 4 7 8 50 42 2
pre
in
post
delete
15
delete
88
in
search
8
search
222
insert
15
pre
in
post
exit

样例输出:

31 15 9 5 4 2 7 8 50 42
2 4 5 7 8 9 15 31 42 50
2 4 8 7 5 9 15 42 50 31
TRUE
FALSE
2 4 5 7 8 9 31 42 50
YES
NO
31 9 5 4 2 7 8 15 50 42
2 4 5 7 8 9 15 31 42 50
2 4 8 7 5 15 9 42 50 31

注意:在样例中,我先把15删除掉了,然后再插入15,观察最开始的三个遍历,和最后的三次遍历,遍历结果是有区别的。

import java.util.*;

public class Xingyuxingxi {
    static TreeNode root;
    static boolean pd;//定义全局变量,就无需导入到方法里面
    public static class TreeNode{
        TreeNode lc;
        TreeNode rc;
        int item;
        public TreeNode(int item) {
            this.item=item;
        }
    }
    public static TreeNode insert(TreeNode root,int item) {
        if(root==null) {//如果要插入的位置为空,则直接加入新结点
            root=new TreeNode(item);
        }
        else if(item > root.item) {//如果插入的数大该结点的数则进该结点的右子树找位置
            root.rc=insert(root.rc,item);
        }
        else if(item< root.item) {//如果插入的数小于该结点的数则进该结点的左子树找位置
            root.lc=insert(root.lc,item);
        }
        return root;
    }
    public static TreeNode delete(TreeNode root,int item){
        if(root==null)
        {
            return null;
        }
    if(root.item==item) {
        pd=true;
        if (root.lc == null && root.rc == null) {//如果删除的结点左子树和右子树都为空
            root = null;//则直接删除该结点
        } else if (root.lc != null) {//如果删除结点的左子树不为空,应该在左子树中找到最大的结点
            TreeNode node1 = root.lc;//储存该结点的左子树结点
            TreeNode node2 = root.lc;//储存该结点的左子树结点
            while (node1.rc != null) {//最大的值肯定在左子树结点的右子树上,如果没有则该结点就是最大值,因为二叉搜索树要求左子树小于前结点,右子树大于前结点
                node2 = node1;
                node1 = node1.rc;
            }//如果进了循环,则node1和node2不相等
            if (node1 != node2) {//如果不相等表示,则node2储存的将会是node1的父亲结点,node1储存的是node2的右子树结点
                node2.rc = node1.lc;//让node2右子树结点连接node1的左子树结点,此时node1已经是最大的,所以没有右子树
                root.item = node1.item;//删除结点用删除结点左子树的最大值替换
            } else {//如果两个储存的结点相等,则该结点无右结点,只需要将删除结点替换为该结点并且连接其原本的左子树结点即可
                root.item = node1.item;
                root.lc = node1.lc;
            }
        } else {//如果删除结点的右子树不为空,应该在右子树中找到最小的结点
            TreeNode node1 = root.rc;//储存该结点的左子树结点
            TreeNode node2 = root.rc;//储存该结点的左子树结点
            while (node1.lc != null) {//最小的值肯定在右子树结点的左子树上,如果没有则该结点就是最小值,因为二叉搜索树要求左子树小于前结点,右子树大于前结点
                node2 = node1;
                node1 = node1.lc;
            }//如果进了循环,则node1和node2不相等
            if (node2 != node1) {//如果不相等表示,则node2储存的将会是node1的父亲结点,node1储存的是node2的左子树结点
                node2.lc = node1.rc;//让node2左子树结点连接node1的右子树结点,此时node1已经是最小的,所以没有左子树
                root.item = node1.item;//删除结点用删除结点左子树的最大值替换
            } else {//如果两个储存的结点相等,则该结点无左结点,只需要将删除结点替换为该结点并且连接其原本的右子树结点即可
                root.item = node1.item;
                root.rc = node1.rc;
            }
        }
    }
    else if(item<root.item){//如果删除的结点比该结点小,进左子树找
        root.lc=delete(root.lc,item);
    }
    else {//如果大则进右子树找
        root.rc=delete(root.rc,item);
    }
    return root;
    }
    public static void search(int item) {
        TreeNode node = root;
        while(node!=null) {
            if(item<node.item){//如果小于该结点则进左边找
                node=node.lc;
            } else if (item>node.item){//大于则进右边找
                node=node.rc;
            }else {//找到了就退出
                pd=true;//标记为true
                break;
            }
        }
    }
    public static void pre(TreeNode root) {//先序遍历递归顺序,中左右
        if(root==null) {//如果根结点为空则返回
            return;
        }
        System.out.print(root.item+" ");//中
        pre(root.lc);//左
        pre(root.rc);//右
    }
    public static void in(TreeNode root) {//中序遍历递归顺序,左中右
        if(root==null) {//如果根结点为空则返回
            return;
        }
        in(root.lc);//左
        System.out.print(root.item+" ");//中
        in(root.rc);//右
    }
    public static void post(TreeNode root) {//后序遍历递归顺序,左右中
        if(root==null) {//如果根结点为空则返回
            return;
        }
        post(root.lc);//左
        post(root.rc);//右
        System.out.print(root.item+" ");//中
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        root=null;//初始化
        for (int i = 0; i < n; i++) {
            int item=sc.nextInt();
            root=insert(root,item);//就是插入操作
        }
        String str;
        while(sc.hasNext()) {
            str=sc.next();
            if(str.equals("exit")) {//退出
                break;
            } else if(str.equals("insert")) {//插入
                int item=sc.nextInt();
                root=insert(root,item);
            } else if(str.equals("delete")) {//删除
            int item=sc.nextInt();
            pd=false;
            root=delete(root,item);
            if(pd){//如果成功删除"TRUE"
                System.out.println("TRUE");
            }else {//否则"FALSE",实际上只有没有要删除的数才为"FALSE"
                System.out.println("FALSE");
            }
            } else if(str.equals("search")) {//查找
            int item= sc.nextInt();
            pd=false;
            search(item);
            if(pd){//找到则为"YES"
                System.out.println("YES");
            } else {//否则为"NO"
                System.out.println("NO");
            }
            } else if(str.equals("pre")) {//先序遍历
            pre(root);
            System.out.println();
            } else if(str.equals("in")) {//中序遍历
            in(root);
            System.out.println();
            } else if(str.equals("post")) {//后序遍历
            post(root);
            System.out.println();
            }
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星与星熙.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值