二叉樹搜索樹(Java實現)

代碼如下(附有註釋):

package DataStructureDemo.com.ds.tree;


import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class BinarySearchTree<E extends Comparable<E>> {

    private class Node{
        E val;
        Node left,right;

        Node(E val) {
            this.val = val;
        }

    }

    private Node root;//二叉搜索樹的根結點
    private int size;//二叉搜索樹中元素個數

    //構造器,默認生成一個空二叉搜索樹
    private BinarySearchTree() {
        this.root = null;
        this.size = 0;
    }

    public int getSize() {
        return size;
    }

    public boolean isEmpty(){
        return this.size == 0;
    }


    //向二分搜索樹中添加新元素
    public void add(E e){
       root = add(root,e);
    }


    //向以node爲根結點的樹中插入元素e(遞歸)
    //返回插入新節點後二叉樹的根
    private Node add(Node node,E e){
       if(node == null){
           size++;
           return new Node(e);
       }

        //要插入元素小於根節點值,使用遞歸
        if(e.compareTo(node.val) <0){
            node.left = add(node.left,e);
        }else if(e.compareTo(node.val) >0){

            //要插入元素大於根節點值
            node.right = add(node.right,e);
        }

        return node;
    }


    //二叉搜索樹中是否包含元素e
    public boolean contains(E e){
        return contains(root,e);
    }

    //看以node爲根結點的二叉搜索樹是否包含元素e(遞歸)
    private boolean contains(Node node,E e){

        if(node == null){
            return false;
        }

        if(e.compareTo(node.val) == 0){
            return true;
        } else if(e.compareTo(node.val) <0) {
            return contains(node.left,e);
        } else {
            return contains(node.right,e);
        }

    }

    //二叉搜索樹的前序遍歷
    public void PreOrder(){
        PreOrder(root);
    }

    //前序遍歷以node爲根節點的二叉搜索樹(遞歸)
    //先訪問根節點,再訪問左右子樹
    private void PreOrder(Node node){
        //遞歸終止條件
        if(node == null){
            return;
        }

        System.out.print(node.val+" ");

        if (node.left != null) {
            PreOrder(node.left);
        }

        if (node.right != null) {
            PreOrder(node.right);
        }
    }

    //前序遍歷的非遞歸寫法,用棧來記錄遍歷的過程
    public void PreOrderNR(){
        Stack<Node> stack = new Stack<>();
        stack.push(root);//先將根節點壓入棧中,作爲前序遍歷第一個訪問的

        while(!stack.isEmpty()){
            Node cur = stack.pop();

            System.out.print(cur.val+" ");//訪問節點

            //鑑於棧後進先出的性質,應先將右子樹壓入棧中
            if(cur.right != null){
                stack.push(cur.right);
            }

            if(cur.left != null){
                stack.push((cur.left));
            }
        }
    }

    //中序遍歷 先訪問左子樹,再訪問根節點,最後訪問右子樹
    public void Inorder(){
        Inorder(root);
    }

    private void Inorder(Node node) {
        if(node == null){
            return;
        }

        if(node.left != null){
            Inorder(node.left);
        }

        System.out.print(node.val+" ");

        if(node.right != null){
            Inorder(node.right);
        }

    }


    //後序遍歷  先訪問左右子樹,再訪問根節點
    public void PostOrder() {
        postOrder(root);
    }

    private void postOrder(Node node){
        if(node == null) {
            return;
        }

        if (node.left != null) {
            postOrder(node.left);
        }

        if (node.right != null) {
            postOrder(node.right);
        }

        System.out.print(node.val+" ");
    }

    //層序遍歷(非遞歸形式)
    public void LevelOrder(){
        Queue<Node> q = new LinkedList<>();
        q.add(root);

        while(!q.isEmpty()){
            Node cur = q.remove();

            System.out.print(cur.val+" ");

            if(cur.left != null){
                q.add(cur.left);
            }

            if(cur.right != null){
                q.add(cur.right);
            }
        }
    }

    public E getMin() {
        if(root == null){
            throw new IllegalArgumentException();
        }

        Node node =  getMinNode(root);
        return node.val;
    }



    //查找以node爲根節點的二叉搜索樹的最小值節點
    private Node getMinNode(Node node){
        return (node.left != null) ? getMinNode(node.left) : node;
    }


    public E getMax() {
        if(root == null){
            throw new IllegalArgumentException();
        }

        Node node = getMaxNode(root);
        return node.val;
    }


    //查找查找以node爲根節點的二叉搜索樹的最大值節點
    private Node getMaxNode(Node node){
        return (node.right == null) ? node : getMaxNode(node.right);
    }


    public E RemoveMin(){
        E res = getMin();
        root = RemoveMinNode(root);
        return res;
    }

    //刪除傳入二叉樹的最小值節點
    private Node RemoveMinNode(Node node){

        //找到需要刪除的節點(遞歸終止條件)
        if(node.left == null){
           Node rightnode = node.right;
           node.right = null;
           size--;
           return rightnode;
        }

        //繼續向左走,刪除最小值節點
        node.left = RemoveMinNode(node.left);
        return node;
    }


    public E RemoveMax() {
       E res = getMax();
       root = RemoveMaxNode(root);
       return res;
    }


    private Node RemoveMaxNode(Node node){
        if(node.right == null){
            Node leftnode = node.left;
            node.left = null;
            size--;
            return leftnode;
        }

        node.right = RemoveMaxNode(node.right);
        return node;
    }


    //移除二叉樹中指定值的節點
    public void remove(E e) {
        root = remove(root,e);
    }

    private Node remove(Node node,E e){
        if(node == null){
            return null;
        }

        //需要刪除的節點在左子樹中
        if(e.compareTo(node.val) <0){
            node.left = remove(node.left,e);
        }
        //需要刪除的節點在右子樹中
        else if(e.compareTo(node.val) >0){
            node.right = remove(node.right,e);
        }

        //此時node即爲需要刪除的節點
        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.left != null){
                Node successor = getMinNode(node.right);
                successor.left = node.left;
                successor.right = RemoveMinNode(node.right);
                node.left = node.right = null;
                return successor;
            }
        }

        return node;
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        generateString(root, 0, res);
        return res.toString();
    }

    // 生成以node爲根節點,深度爲depth的描述二叉樹的字符串
    private void generateString(Node node, int depth, StringBuilder res){

        if(node == null){
            res.append(generateDepthString(depth)).append("null\n");
            return;
        }

        res.append(generateDepthString(depth)).append(node.val).append("\n");
        generateString(node.left, depth + 1, res);
        generateString(node.right, depth + 1, res);
    }

    private String generateDepthString(int depth){
        StringBuilder res = new StringBuilder();
        for(int i = 0 ; i < depth ; i ++)
            res.append("--");
        return res.toString();
    }


    public static void main(String[] args) {
        BinarySearchTree<Integer> bst = new BinarySearchTree<>();
       int[] a = {5,3,6,8,4,2};
        for (int k : a) {
            bst.add(k);
        }


        System.out.println("遞歸前序遍歷結果爲:");
        bst.PreOrder();//前序遍歷
        System.out.println();
        System.out.println("遞歸後序遍歷結果爲:");
        bst.PostOrder();//後序遍歷
        System.out.println();
        System.out.println("遞歸中序遍歷結果爲:");
        bst.Inorder();//中序遍歷
        System.out.println();

        /*System.out.println(bst.getMax());
        System.out.println(bst.getMin());*/

        System.out.println("非遞歸前序遍歷結果爲:");
        bst.PreOrderNR();

        //System.out.println(bst.toString());

        System.out.println();
        System.out.println("層序遍歷結果爲:");
        bst.LevelOrder();

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章