二叉树查找删除实现

如何实现  二叉树查找删除实现:(原创,仅供学习,和知识积累)


package com;

import java.util.NoSuchElementException;

/**
 * 二叉树查找删除实现
 *
 */
public class SearchBinary {

    private TreeNode root;

    public TreeNode getRoot(){
        return root;
    }

    //排序输出
    public void midOrderTraverse(TreeNode root){
        if(root==null){
            return;
        }
        midOrderTraverse(root.leftChild);
        System.out.print(root.data+" ");
        midOrderTraverse(root.rightChild);
    }

    /**
     * 遍历查找左根节点
     * @param node
     * @return
     */
    private TreeNode getMinLeftTreeNode(TreeNode node) {
        TreeNode curRoot = null;
        if (node == null) {
            return null;
        } else {
            curRoot = node;
            while(curRoot.leftChild != null) {
                curRoot = curRoot.leftChild;
            }
        }
        return curRoot;
    }


    /**
     * 添加节点
     * 1.先查找,找到这个节点相关的位置
     * 2.添加再查找
     *
     */
    public TreeNode put(int data){
        if(root==null){
            TreeNode node=new TreeNode(data);
            root=node;
            return node;
        }

        TreeNode parent=null;
        TreeNode node=root;
        //查找相关的根节点
        for( ;node != null; ){
            parent=node;
            if(data<node.data){//向左节点查找
                node=node.leftChild;
            }else if(data>node.data){//向右节点查找
                node=node.rightChild;
            }else{
                return node;
            }
        }

        TreeNode newNode=new TreeNode(data);
        //插入节点
        if(data<parent.data){
            parent.leftChild=newNode;
        }else{
            parent.rightChild=newNode;
        }

        //有坑
        newNode.parent=parent;
        return newNode;
    }


    /**
     * 查找节点
     * 思路  循环遍历 ,直至相当
     *
     */
    public TreeNode findNode(int data){
        if(root == null){
            return null;
        }
        TreeNode node=root;
        for(;node!=null;){
            if(node.data==data){
                return node;
            }else if(node.data<data){
                node=node.rightChild;
            }else if(node.data>data){
                node=node.leftChild;
            }
        }
        return null;
    }



    /**
     * 删除一个节点p
     * 1.查找该节点p右子节点的左根节点s,s替代被删除节点的位置,s的左子节点为p的左子节点
     * 2.s的父节点的左孩子(此时以为null)指向s的右子节点
     * 3.s的右子节点指向p的游子节点
     * 4.p的父节点的指向该节点s(p若为左,则s为父节点的左子节点。反之,为右)
     */
    public void delNode(TreeNode node){
        if(node==null){
            throw new NoSuchElementException();
        }else{
            TreeNode parent=node.parent;

            if(node.leftChild==null || node.rightChild==null){
                //没有孩子
                if(parent==null){
                    //只有一个根节点
                    root=null;
                }else if(parent.leftChild==node){
                    parent.leftChild=null;
                }else if(parent.rightChild==node){
                    parent.rightChild=null;
                }
            }else if(node.leftChild!=null || node.rightChild==null){
                //node只有左孩子
                if(parent==null){
                    //此时node是顶点
                    root=node.leftChild;
                    node.leftChild.parent=null;
                }else{
                    //判断node是parent的左子还是右子
                    if(parent.leftChild==node){
                        parent.leftChild=node.leftChild;
                    }else{
                        parent.rightChild=node.leftChild;
                    }
                    //此时node的左子的父必须要指向ndoe的父
                    node.leftChild = parent;//#######
                    node.parent=null;
                }
            }else if(node.leftChild==null || node.rightChild==null){//3:只有右孩子

                if(parent==null){
                    //此时node是顶点
                    root=node.rightChild;
                    node.rightChild.parent=null;
                }else{
                    if(parent.leftChild==node){
                        parent.leftChild=node.rightChild;
                    }else{
                        parent.rightChild=node.rightChild;
                    }
                    node.rightChild.parent=parent;
                    node.parent=null;
                }
            }else if(node.leftChild!=null || node.rightChild!=null){//4:有左右两个子节点

                if(node.rightChild.leftChild==null){
                    //1:删除节点的右子树的左子树是否为空,如果为空,则把要删除节点的左子树设为删除点的右子树的左子树

                    if(parent==null){
                        root=node.rightChild;
//                        node.parent=null;
                    }else{
                        if(parent.leftChild==node){

                            //父的左子等于node的右子
                            parent.leftChild=node.rightChild;
                            //node的右子的左子  为node的左子
                            node.rightChild.leftChild=node.leftChild;
                            //node左子 的父为node的right
//                             node.leftChild.parent=node.rightChild;
                        }else{

                            //父的左子等于node的右子
                            parent.leftChild=node.rightChild;
                            //node的右子的左子  为node的左子
                            node.rightChild.leftChild=node.leftChild;
                            //node左子 的父为node的right
//                             node.leftChild.parent=node.rightChild;
                        }
                        node.parent=null;
                    }
                }else{
                    //最左子数s(没有左子节点)
                    TreeNode s=getMinLeftTreeNode(node);
                    // 1:最左子数的左子节点为node的左子节点
                    s.leftChild=node.leftChild;
                    node.leftChild.parent=s;

                    // 2:s的父的左子节点为s的右节点
                    s.parent.leftChild=s.rightChild;
                    s.rightChild.parent=s.parent;

                    // 3:s的右节点为node的右节点
                    s.rightChild=node.rightChild;
                    node.rightChild.parent=s;


                    // 4:node的parent的子指向s
                    if(parent==null){
                        root=s;
                    }else{
                        if(parent.leftChild==node){
                            parent.leftChild=s;
                        }else{
                            parent.rightChild=s;
                        }
                        s.parent=node.parent;
                    }
                }
            }
        }
    }


    public class TreeNode<T>{
        int  data;
        TreeNode<T> parent;
        TreeNode<T> leftChild;
        TreeNode<T> rightChild;
        public TreeNode(int data) {
            super();
            this.data = data;
            this.parent = null;
            this.leftChild = null;
            this.rightChild = null;
        }
        public int getNode() {
            return data;
        }
        public void setNode(int data) {
            this.data = data;
        }
        public TreeNode<T> getParent() {
            return parent;
        }
        public void setParent(TreeNode<T> parent) {
            this.parent = parent;
        }
        public TreeNode<T> getLeftChild() {
            return leftChild;
        }
        public void setLeftChild(TreeNode<T> leftChild) {
            this.leftChild = leftChild;
        }
        public TreeNode<T> getRightChild() {
            return rightChild;
        }
        public void setRightChild(TreeNode<T> rightChild) {
            this.rightChild = rightChild;
        }
    }

    public static void main(String[] args) {
        int[] arrays = {12, 3 ,23, 5 ,8, 1, 19};
        SearchBinary tree = new SearchBinary();
        for(int i: arrays) {
            tree.put(i);
        }
        tree.midOrderTraverse(tree.root);
        System.out.println();
        System.out.println("------查找-------");
        TreeNode node = tree.findNode(1);
        System.out.println(node !=null ? node.data: null);
        System.out.println("------删除-------");
        tree.delNode(node);
        System.out.println("删除"+node.data);
        tree.midOrderTraverse(tree.root);

    }



}


控制台运行结果如下:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值