【数据结构】Java实现二分搜索树

接口:

package bin_tree;

/**
 * @program: bintree
 * @description: 二叉树通用接口
 * @author: fwb
 * @create: 2019-06-05 19:45
 **/
public interface BInTree<E> {
    void add(E e);
    boolean contains(E e);
    void preOrder();//前序遍历
    void inOrder();//中序遍历
    void postOrder();//后序遍历
    E getMin();//取得最小值
    E getMax();
    E removeMin();
    E removeMax();
    void remove(E e);//移除指定节点
    int size();//取得节点个数
//    void floor();//小于该值在二叉树中的最大节点
//    void ceil();//大于该值在二叉树中的最小节点
//    void rank();//给每个节点排序
//    void select();//给出顺序,求节点
}

主程序:

package bin_search_tree;

import bin_tree.BInTree;

/**
 * @program: bintree
 * @description:
 * @author: fwb
 * @create: 2019-06-05 19:51
 **/
public class BinSearchTree<E extends Comparable<E>> implements BInTree<E> {

    private class Node{
        E data;
        Node left;
        Node right;

        public Node(E e) {
            data = e;
        }
    }
    private Node root;
    private int size;

//    public void add(E e) {
//        if (root == null){
//            Node node = new Node(e);
//            root = node;
//            size++;
//        }
//        //递归寻找插入位置
//        add(root,e);
//    }
//    /**
////    * @Description:  以指定节点node为根节点,插入指定元素e
////    * @Param: [node, e]
////    * @return: void
////    */
////    private void add(Node node,E e){
////        //插入的值刚好是当前树根节点的值
////        if (node.data.compareTo(e) == 0){
////            return;
////        }
////        //找到插入位置,在左子树做插入(小的放左边)
////        else if(e.compareTo(node.data) < 0 && node.left == null){
////            Node newNode = new Node(e);
////            node.left = newNode;
////            size++;
////        }
////        //找到插入位置,在左子树做插入(大的放右边)
////        else if (e.compareTo(node.data) > 0 && node.right == null){
////            Node newNode = new Node(e);
////            node.right = newNode;
////            size++;
////        }
////        else if (e.compareTo(node.data) < 0){
////            //递归寻找左树位置
////            add(node.left,e);
////        }else{
////            // 递归寻找右树位置
////            add(node.right,e);
////        }
////    }

    //优化后的add方法
    public void add(E e) {
        root = add(root,e);
    }
    /**
    * @Description: 以当前node作为根节点,插入元素为e的节点,返回插入后的树的根节点。
    * 根据传入的根节点的数,找到他的插入位置,返回调整后的新的树的根节点
    * @Param: [node, e]
    * @return: void
    */
    private Node add(Node node,E e){
        //如果为空
        if (node == null){
            Node newNode = new Node(e);
            size++;
            return newNode;
        }
        //如果不为空,判断此时e到底是在左树还是在右树插入
        if (e.compareTo(node.data) < 0){
            node.left = add(node.left,e);
        }
        if (e.compareTo(node.data) > 0){
            node.right = add(node.right,e);
        }
        return node;
    }

    @Override
    public boolean contains(E e) {
        if (root == null){
            return false;
        }
        return contains(root,e);
    }

    //递归
    private boolean contains(Node node,E e){
        if (node == null){
            return false;
        }
        if (node.data.compareTo(e) == 0){
            return true;
        }
        else if (e.compareTo(node.data) < 0){
            return contains(node.left,e);
        }else {
            return contains(node.right,e);
        }
    }

    @Override
    public void preOrder() {
        preOrder(root);
    }
    /***
    * @Description: 以当前节点作为根节点进行前序遍历
    * @Param: [node]
    * @return: void
    */
    private void preOrder(Node node) {
        if (node == null)
            return;
        System.out.println(node.data);
        preOrder(node.left);
        preOrder(node.right);
    }

    @Override
    public void inOrder() {
        inOrder(root);
    }

    /***
    * @Description: 以node为根节点进行中序遍历
    * @Param: [node]
    * @return: void
    */
    private void inOrder(Node node){
        if (node == null){
            return;
        }
        inOrder(node.left);
        System.out.println(node.data);
        inOrder(node.right);
    }


    @Override
    public void postOrder() {
        postOrder(root);
    }

    private void postOrder(Node node){
        if (node == null){
            return;
        }
        postOrder(node.left);
        postOrder(node.right);
        System.out.println(node.data);
    }

    //不一定是做左子树的叶子节点,应该一直递归向左走直到走不动为止,此时节点即为所求。
    @Override
    public E getMin() {
        if (root == null)
            throw new IllegalArgumentException("BST is empty!");
        Node node  = getMinNode(root);
        return node.data;
    }
    /**
    * @Description: 查找以node为根节点的二分搜索树的最小值节点。
    * @Param: [node]
    * @return: bin_search_tree.BinSearchTree.Node
    */
    private Node getMinNode(Node node){
       if (node.left == null){
           return node;
       }
       return getMinNode(node.left);
    }
    //应该一直递归向右走直到走不动为止,此时节点即为所求。
    @Override
    public E getMax() {
        if (root == null)
            throw new IllegalArgumentException("BST is empty!");
        Node node = getMaxNode(root);
        return node.data;
    }

    private Node getMaxNode(Node node){
        if (node.right == null){
            return node;
        }
        return getMaxNode(node.right);
    }

    @Override
    public E removeMin() {
        E result = getMin();
        root = removeMInNode(root);
        return result;
    }

    /**
    * @Description: 删除传入二叉树的最小值节点,返回删除后二叉树的根节点。
    * @Param: [node]
    * @return: bin_search_tree.BinSearchTree.Node
    */
    private Node removeMInNode(Node node){
        //找到需要删除的节点
        if (node.left == null){
            Node rigthNode = node.right;
            node.right = null;
            size--;
            return rigthNode;
        }
        //向左一直走直到找到最小值节点
        node.left = removeMInNode(node.left);
        return node;
    }

    @Override
    public E removeMax() {
        E result = getMax();
        root = removeMaxNode(root);
        return result;
    }

    private Node removeMaxNode(Node node){
        if (node.right == null){
            Node leftNode = node.left;
            node.left = null;
            size--;
            return leftNode;
        }
        node.right = removeMInNode(node.right);
        return node;
    }

    /*
    HIbbard Deletion
    找到该节点的前驱或者后继节点,替换(找左子树的右节点,找右子树的左节点)
     */
    public void remove(E e) {
        root = remove(root,e);
    }
    /**
    * @Description:删除以node为根节点且值为e的节点,返回删除后的二叉树根节点
    * @Param:
    * @return:
    */
    private Node remove(Node node,E e){
        if (node == null){
            return null;
        }
        //如果节点.data < e,则在节点的左子树中寻找
        if (e.compareTo(node.data) < 0){
            node.left = remove(node.left,e);
        }
        //如果节点.data > e,则在节点的右子树中寻找
        if (e.compareTo(node.data) > 0){
            node.right = remove(node.right,e);
        }
        //此时node就为要删除的节点(此时node.data == e)
        else{
            //若此时节点只有一边孩子
            if (node.left != null && node.right == null){
                Node leftNode = node.left;
                size--;
                node.left = null;
                return leftNode;
            }
            if (node.right != null && node.left == null){
                Node rightNode = node.right;
                size--;
                node.right = null;
                return rightNode;
            }
            if (node.right != null && node.right != null){
                //首先找到前驱或者后继节点(左树最大,右树最小)
                Node successor = getMinNode(node.right);
                //将原节点的左子树链在后继节点上(右子树中最小的)
                successor.left = node.left;
                //将原节点的删除了后继节点的右子树链接在后继节点上
                successor.right = removeMInNode(node.right);
                //删除node
                node.left = node.right = null;
                return successor;
            }
        }
        return node;
    }

    public int size() {
        return size;
    }

    public String toString(){
        StringBuilder res = new StringBuilder();
        genrateTreeStruct(root,0,res);
        return res.toString();
    }
    //输出当前树的结构(根据前序遍历)
    private void genrateTreeStruct(Node node,int depth,StringBuilder res){
        if (node == null){
            res.append("null" + "\n");
            return;
        }
        res.append(generateGang(depth) + node.data + "\n");
        genrateTreeStruct(node.left,depth + 1,res);
        genrateTreeStruct(node.right,depth + 1,res);
    }
    private String generateGang(int depth){
        StringBuilder sb = new StringBuilder();
        for (int i = 0;i < depth;i++){
            sb.append("--");
        }
        return sb.toString();
    }
}

测试文件:

package bin_search_tree;

import bin_tree.BInTree;

import java.util.ArrayList;
import java.util.List;


/**
 * @program: bintree
 * @description:
 * @author: fwb
 * @create: 2019-06-05 20:21
 **/
public class Test {
    public static void main(String[] args) {
        BInTree<Integer> binTree = new BinSearchTree<>();
        int[] num = new int[]{28,16,13,22,30,29,42};
        for (int i = 0; i < num.length; i++) {
            binTree.add(num[i]);
        }
        binTree.preOrder();
        System.out.println("-------------------");
        binTree.inOrder();
        System.out.println("-------------------");
        binTree.postOrder();
        System.out.println("-------------------");
        System.out.println(binTree);
        System.out.println("-------------------");
        System.out.println(binTree.getMin());
        List<Integer> list = new ArrayList<>();
        while (binTree.size() != 0){
            list.add(binTree.removeMin());
        }
        System.out.println(list);
        System.out.println(binTree.size());
    }

}

你可能感兴趣的:(数据结构)