1. 程式人生 > >基礎資料結構與演算法實現(2)—二叉搜尋樹BST

基礎資料結構與演算法實現(2)—二叉搜尋樹BST

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


public class BST <E extends Comparable<E>> {
        
        private class Node{
                public E e;
                public Node left,right;
                
                public Node(E e) {
                        this.e=e;
                        left = null;
                        right = null;
                }
        }
        
        private Node root;
        private int size;
        
        public BST() {
                root = null;
                size = 0;
        }
        
        public int size() {
                return size;
        }
        
        public boolean isEmpty() {
                return size==0;
        }
        
        //新增操作
        public void add(E e) {
                root = add(root,e);
        }
        
        private Node add(Node node,E e) {
                
                if(node==null) {
                        size++;
                        return new Node(e);
                }
                
                if(e.compareTo(node.e) < 0)
                        node.left = add(node.left,e);
                else if(e.compareTo(node.e)>0)
                        node.right  = add(node.right,e);
                
                return node;
                
        }
        
        
        //看BST中是否包含元素e
        public boolean contains(E e) {
                return contains(root,e);
        }
        
        
        //看以node為根的BST中是否包含元素e,遞迴演算法
        private boolean contains(Node node,E e) {
                
                if(node==null) {
                        return false;
                }
                
                if(e.compareTo(node.e)==0) {
                        return true;
                }else if(e.compareTo(node.e)<0) {
                        return contains(node.left,e);
                }else {
                        return contains(node.right,e);
                }
                
        }
        
        
        //前序遍歷 遞迴實現
        public void preOrder() {
                preOrder(root);
        }
        
        private void preOrder(Node node) {
                
                if(node == null)
                        return;
                
                System.out.println(node.e); //先訪問節點
                preOrder(node.left);
                preOrder(node.right);
                
        }
        
        
        //中序遍歷 按照從小到大的順序(排序樹)
        public void inOrder() {
                inOrder(root);
        }
        
        private void inOrder(Node node) {
                
                if(node == null) {
                        return;
                }
                
                inOrder(node.left);
                System.out.println(node.e); //先訪問節點
                inOrder(node.right);
                
        }
        
        
        //後序遍歷  
        //應用之一是為BST釋放記憶體,先釋放子節點
        public void postOrder() {
                postOrder(root);
        }
        
        private void postOrder(Node node) {
                
                if(node == null) {
                        return;
                }
                
                postOrder(node.left);
                postOrder(node.right);
                System.out.println(node.e); //最後訪問節點
                
        }
        
        //層序遍歷(廣度優先遍歷) 用佇列來實現
        public void levelOrder() {
                Queue<Node>  q = new LinkedList<>();
                q.add(root);
                
                //讓節點出隊,同時讓節點的子節點入隊
                while(!q.isEmpty()) {
                        
                        Node cur = q.remove();
                        System.out.println(cur.e);
                        
                        if(cur.left != null)
                                q.add(cur.left);
                        if(cur.right != null)
                                q.add(cur.right);
                }
        }
        
        //尋找二分搜尋樹的最小元素
        public E minimum() {
                if(size==0)
                        throw new IllegalArgumentException("BST is Empty!");
                
                return minimum(root).e;
        }
        
        private Node minimum(Node node) {
                if(node.left==null)
                        return node;
                return minimum(node.left);
        }
        
        //刪除BST中的最小元素
        public E removeMin() {
                E ret = minimum();
                root = removeMin(root);
                return ret;
        }
        
        private Node removeMin(Node node) {
                
                if(node.left == null) {
                        Node rightNode=node.right;
                        node.right = null;
                        size --;
                        return rightNode;
                }
                
                node.left = removeMin(node.left);
                
                return node;
                
        }
        
        //從二分搜尋樹中刪除元素e的節點
        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.e) < 0) {
                        node.left = remove(node.left,e);
                        return node;
                }else if(e.compareTo(node.e) > 0) {
                        node.right = remove(node.right, e);
                        return node;
                }else {
                        
                        //待刪除節點左子樹為空的情況
                        if(node.left == null) {
                                Node rightNode = node.right;
                                node.right = null;
                                size--;
                                return rightNode;
                        }
                        
                        //待刪除節點右子樹為空的情況
                        if(node.right == null) {
                                Node leftNode = node.left;
                                node.left = null;
                                size--;
                                return leftNode;
                        }
                        
                        //待刪除節點左右子樹均不為空的情況
                        //找到比待刪除節點大的最小節點,即待刪除節點右子樹的最小節點
                        //用這個節點頂替待刪除節點的位置
                        
                        Node successor = minimum(node.right);
                        successor.right = removeMin(node.right);
                        successor.left = node.left;
                        
                        node.left = node.right = null;
                        
                        return successor;
                }
        }
        
        
        
        //以前序遍歷實現列印BST
        @Override
        public String toString() {
                StringBuilder res = new StringBuilder();
                generateBSTString(root,0,res);
                return res.toString();
        }
        //生成以node為根節點,深度為depth的描述二叉樹的字串
        private void generateBSTString(Node node,int depth,StringBuilder res) {
                
                if(node == null) {
                        res.append(generateDepthString(depth)+"null\n");
                        return;
                }
                
                res.append(generateDepthString(depth)+node.e+"\n");
                generateBSTString(node.left, depth+1, res);
                generateBSTString(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();
        }
        
        
        
        
}