二叉搜索树

二叉树的定义:二叉树是每个结点最多有两个子树的树结构,通常子树被称作“左子树”和“右子树”。二叉树的每个结点最多只有两棵子树,二叉树的子树有左右之分,次序不能颠倒。

下图为一颗二叉树:
这里写图片描述

二叉搜索树的定义:它是具有下列性质的二叉树,若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;它的左右子树也分别为二叉搜索树。

下图为一棵二叉搜索树:
这里写图片描述

下面给出二叉搜索树的建立,删除,遍历(包括前序、中序、后序的递归以及非递归遍历):

import java.util.Stack;

/**
 * 二叉树
 * @author zxy
 *
 */
public class TreeNode {

    private int val; //结点数据

    private TreeNode left; //左子树
    private TreeNode right; //右子树

    public TreeNode(int val) {
        super();
        this.val = val;
    }

    /**
     * 创建二叉搜索树
     * @param vals
     * @return
     */
    public static TreeNode createTree(int[] vals){
        if(vals==null || vals.length==0){
            return null;
        }
        TreeNode root=new TreeNode(vals[0]);
        for(int i=1;i<vals.length;i++){
            insertTree(root, vals[i]);
        }
        return root;
    }

    /**
     * 向二叉搜索树中插入一个结点
     * @param root
     * @param val
     */
    public static void insertTree(TreeNode root, int val){
        if(root==null){
            return;
        }else{
            TreeNode node=root;
            while(node!=null){
                //指向当前结点的上一结点
                TreeNode p=node;
                if(val<node.val){
                    node=node.left;
                    if(node==null){
                        p.left=new TreeNode(val);
                    }
                }else{
                    node=node.right;
                    if(node==null){
                        p.right=new TreeNode(val);
                    }
                }
            }
        }
    }

    /**
     * 二叉树中删除一个结点
     * @param root
     * @param val
     */
    public static void deleteTree(TreeNode root, int val){
        if(root==null){
            return;
        }
        TreeNode node=root;
        while(node!=null){
            //指向当前结点的上一结点
            TreeNode p=node;
            //删除结点的值小于当前结点的值
            if(val<node.val){
                node=node.left;
                if(node!=null){
                    //当前结点的值等于删除结点的值
                    if(node.val==val){
                        //当前结点没有左子树
                        if(node.left==null){
                            //当前结点也没有右子树
                            if(node.right==null){
                                //上一结点直接赋null
                                p.left=null;
                            //当前结点有右子树
                            }else{
                                //将当前结点的右子树赋给上一结点的左子树
                                p.left=node.right;
                            }
                        //当前结点有左子树
                        }else{
                            //定义两个结点
                            //e_front指向当前结点,e指向当前结点的下一结点
                            TreeNode e_front=node;
                            TreeNode e=node.left;
                            //找到最右端的子树,e_front始终指向e的上一结点
                            while(e.right!=null){
                                e_front=e;
                                e=e.right;
                            }
                            //如果e_font等于当前结点,表示指针没有移动,当前结点的下一结点没有右子树
                            if(e_front==node){
                                e.right=e_front.right;
                                p.left=e;
                            }else{
                            //指针有移动
                                e_front.right=e.left;
                                e.left=node.left;
                                e.right=node.right;
                                p.left=e;
                            }
                        }
                    }
                }
            //删除结点的值大于等于当前结点的值(以下同理)
            }else {
                node=node.right;
                if(node!=null){
                    if(node.val==val){
                        if(node.left==null){
                            if(node.right==null){
                                p.right=null;
                            }else{
                                p.right=node.right;
                            }
                        }else{
                            TreeNode e_front=node;
                            TreeNode e=node.left;
                            while(e.right!=null){
                                e_front=e;
                                e=e.right;
                            }
                            if(e_front==node){
                                e.right=e_front.right;
                                p.right=e;
                            }else{
                                e_front.right=e.left;
                                e.left=node.left;
                                e.right=node.right;
                                p.right=e;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 递归前序遍历
     * @param root
     */
    public static void pre_out_r(TreeNode root){
        if(root!=null){
            System.out.print(root.val+" ");
            pre_out_r(root.left);
            pre_out_r(root.right);
        }
    }

    /**
     * 非递归前序遍历
     * @param root
     */
    public static void pre_out(TreeNode root){
        if(root==null){
            return;
        }
        Stack<TreeNode> stack=new Stack<>();
        while(true){
            while(root!=null){
                //打印当前结点,当前结点入栈,进入其左子树
                System.out.print(root.val+" ");
                stack.push(root);
                root=root.left;
            }
            if(stack.isEmpty()){
                break;
            }
            //退栈,进入其右子树
            root=stack.pop();
            root=root.right;
        }
    }

    /**
     * 递归中序遍历
     * @param root
     */
    public static void in_out_r(TreeNode root){
        if(root!=null){
            in_out_r(root.left);
            System.out.print(root.val+" ");
            in_out_r(root.right);
        }
    }

    /**
     * 非递归中序遍历
     * @param root
     */
    public static void in_out(TreeNode root){
        if(root==null){
            return;
        }
        Stack<TreeNode> stack=new Stack<>();
        while(true){
            //将当前结点和其左子树全部入栈
            while(root!=null){
                stack.push(root);
                root=root.left;
            }
            if(stack.isEmpty()){
                break;
            }
            //退栈,打印当前结点,进入其右子树
            root=stack.pop();
            System.out.print(root.val+" ");
            root=root.right;
        }
    }

    /**
     * 递归后序遍历
     * @param root
     */
    public static void post_out_r(TreeNode root){
        if(root!=null){
            post_out_r(root.left);
            post_out_r(root.right);
            System.out.print(root.val+" ");
        }
    }

    /**
     * 非递归后序遍历
     * 入栈顺序,当前结点入栈->右子树入栈->左子树入栈
     * 出栈顺序,左子树->右子树->当前结点,即为后序遍历
     * @param root
     */
    public static void post_out(TreeNode root){
        if(root==null){
            return;
        }
        //辅助栈
        Stack<TreeNode> stack = new Stack<>();
        //输出栈
        Stack<TreeNode> output = new Stack<>();
        TreeNode p = root;
        while(p!=null||!stack.isEmpty()){
            //当前结点不为空,辅助栈输出栈都入栈,进入其右子树
            if(p!=null){
                stack.push(p);
                output.push(p); //进入待操作栈
                p=p.right; //先进入右子树
            //当前结点为空,辅助栈退栈,进入其左子树
            }else{
                p = stack.pop();
                p = p.left;
            }
        }
        //输出栈出栈,即为后序遍历顺序
        while(!output.isEmpty()){
            TreeNode node = output.pop();
            System.out.print(node.val+" ");
        }
    }

    public static void main(String[] args) {
        int[] vals=new int[]{10,6,20,3,8,15,30,1,7,9,25,40};
        TreeNode root=createTree(vals);
        post_out(root);
        System.out.println();
        deleteTree(root, 20);
        post_out(root);
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值