二叉查找树实现

package com.learn.tree;

/**
 * 二叉查找树
 * 满二叉树:除了叶子节点外,每个节点都有两个子节点
 * 完全二叉树:叶子节点都在最底下两层,最后一层得叶子节点都靠左排列。并且除了最后一层,其他层得节点个数都要达到最大
 * 时间复杂度O(n)
 * @author liuyuzhen 
 */
public class BinarySearchTree {

    private TreeNode root;

    private TreeNode getRoot() {
        return root;
    }

    /**
     * 前序遍历
     * 递归公式: 先打印自己 在打印左节点和右节点
     */
    public void preOrder(TreeNode treeNode) {
        System.out.println(treeNode.getContent());
        if (treeNode.getLeftNode() != null) {
            preOrder(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            preOrder(treeNode.getRightNode());
        }
    }

    /**
     * 中序遍历
     * 递归公式:先打印它得左子树,然后再打印它本身,最后打印他得右子树
     */
    public void innerOrder(TreeNode treeNode) {
        if (treeNode.getLeftNode() != null) {
            innerOrder(treeNode.getLeftNode());
        }
        System.out.println(treeNode.getContent());
        if (treeNode.getRightNode() != null) {
            innerOrder(treeNode.getRightNode());
        }
    }

    /**
     * 后序遍历
     * 递归公式:先打印左子树,然后打印他的右子树,最后打印本身
     */
    private void postOrder(TreeNode treeNode) {
        if (treeNode.getLeftNode() != null) {
            postOrder(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            postOrder(treeNode.getRightNode());
        }
        System.out.println(treeNode.getContent());
    }

    /**
     * 查找
     *
     * @param data 查找的数据
     */
    public TreeNode find(int data) {
        TreeNode p = root;
        while (p != null) {
            if (data == p.getContent()) {
                return p;
            } else if (data < p.getContent()) {
                p = p.getLeftNode();
            } else {
                p = p.getRightNode();
            }
        }
        return null;
    }

    /**
     * 插入
     */
    public void insert(int data) {
        buildTree(root, data);
    }

    /**
     * 删除
     * 1.如果要删除的节点没有子节点,我们只需要直接将父节点中,指向删除节点的指针设置为NULL
     * 2.如果删除的节点只有一个子节点(只有左节点或者只有右节点),我们只需要更新父节点,指向删除节点的指针,让它指向要删除的子节点
     * 3.如果要删除的节点有两个子节点,我们需要找到这个个节点的右子树中的最小节点,把它替换到要删除的节点上。然后再删除这个最小节点,因为最小节点肯定没有左子节点
     */
    public void del(int data) {
        TreeNode p = root;//p指向被删除的节点,初始化指向根节点
        TreeNode pp = null;//pp指向p的夫节点
        while (p != null && p.getContent() != data) {
            pp = p;
            if (data > p.getContent()) {
                p = p.getRightNode();
            } else {
                p = p.getLeftNode();
            }
        }
        //没有找到
        if (p == null) {
            return;
        }
        // 要删除的节点有两个子节点
        if (p.getRightNode() != null && p.getLeftNode() != null) {
            TreeNode minP = p.getRightNode();
            TreeNode minPP = p;
            // 找到该节点的右节点下的最小左节点
            while (minP.getLeftNode() != null) {
                minPP = minP;
                minP = minP.getLeftNode();
            }
            // 将该节点数据替换到P中
            p.setContent(minP.getContent());
            // 下面就变成了删除minP
            p = minP;
            pp = minPP;
        }
        // 删除节点是叶子节点或者只有一个子节点
        TreeNode child;
        if (p.getLeftNode() != null) {
            child = p.getLeftNode();
        } else if (p.getRightNode() != null) {
            child = p.getRightNode();
        } else {
            child = null;
        }
        // 删除的是根节点
        if (pp == null) {
            root = child;
        } else if (pp.getLeftNode() == p) {
            pp.setLeftNode(child);
        } else {
            pp.setRightNode(child);
        }
    }

    /**
     * 快速查找最大节点
     */
    public int findMin() {
        TreeNode p = root;
        while (p.getLeftNode() != null) {
            p = p.getLeftNode();
        }
        return p.getContent();
    }

    /**
     * 快速查找最小节点
     */
    public int findMax() {
        TreeNode p = root;
        while (p.getRightNode() != null) {
            p = p.getRightNode();
        }
        return p.getContent();
    }

    public void buildTree(TreeNode treeNode, int data) {
        // 根节点没有,创建根节点
        if (root == null) {
            root = new TreeNode(data);
        } else {
            if (data < treeNode.getContent()) {
                if (treeNode.getLeftNode() == null) {
                    treeNode.setLeftNode(new TreeNode(data));
                } else {
                    buildTree(treeNode.getLeftNode(), data);
                }
            } else {
                if (treeNode.getRightNode() == null) {
                    treeNode.setRightNode(new TreeNode(data));
                } else {
                    buildTree(treeNode.getRightNode(), data);
                }
            }
        }
    }

    public static BinarySearchTree createBinaryTree(int[] dataArr) {
        BinarySearchTree binaryTree = new BinarySearchTree();
        for (int data : dataArr) {
            binaryTree.buildTree(binaryTree.getRoot(), data);
        }
        return binaryTree;
    }

    /**
     * 72
     * 37      80
     * 29   55
     * 51
     */
    public static void main(String[] args) {
        int[] dataArr = {72, 37, 29, 55, 51, 80};
        BinarySearchTree binaryTree = createBinaryTree(dataArr);
        System.out.println("---------------前序遍历--------------------");
        // 前序遍历
        binaryTree.preOrder(binaryTree.getRoot());

        System.out.println("---------------中序遍历--------------------");
        // 中序遍历
        binaryTree.innerOrder(binaryTree.getRoot());

        System.out.println("---------------后序遍历--------------------");
        // 后序遍历
        binaryTree.postOrder(binaryTree.getRoot());

        System.out.println("---------------查找--------------------");
        // 查找
        TreeNode treeNode = binaryTree.find(80);
        System.out.println(treeNode);
        System.out.println("---------------插入--------------------");
        // 插入
        binaryTree.insert(81);
        binaryTree.preOrder(binaryTree.getRoot());
        // 删除
        System.out.println("---------------删除--------------------");
        binaryTree.del(72);
        binaryTree.preOrder(binaryTree.getRoot());
        // 查找最大
        System.out.println("---------------查找最大\\最小节点--------------------");
        System.out.println(binaryTree.findMax() + "      " + binaryTree.findMin());
    }
}

/**
 * 子节点
 */
class TreeNode {

    // 左节点
    private TreeNode leftNode;
    // 右节点
    private TreeNode rightNode;
    // 存储内容
    private int content;

    public TreeNode getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(TreeNode leftNode) {
        this.leftNode = leftNode;
    }

    public TreeNode getRightNode() {
        return rightNode;
    }

    public void setRightNode(TreeNode rightNode) {
        this.rightNode = rightNode;
    }

    public int getContent() {
        return content;
    }

    public void setContent(int content) {
        this.content = content;
    }

    public TreeNode(int content) {
        this.content = content;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值