二叉樹的java實現

複製代碼
import java.util.Arrays;
import java.util.Stack;


// 鏈式存儲的二叉樹
public class BSTree {
    private TreeNode root = null;
    public TreeNode getRoot() {
        return root;
    }
    public BSTree(TreeNode root) {
        this.root = root;
    }
    
    public boolean isEmpty() {
        return root == null;
    }

    // 樹的高度
    public int height() {
        return TreeNode.height(root);
    }

    // 節點個數
    public int size() {
        return TreeNode.size(root);
    }

    // 返回樹中某節點的父節點
    public TreeNode parent(TreeNode element) {
        return (root == null || root == element) ? null : TreeNode.getParent(root, element);
    }

    
    // 定義樹的節點
    private static class TreeNode {
        private int data;
        private TreeNode leftChild = null;
        private TreeNode rightChild = null;
        
        public TreeNode(int data) {
            this.data = data;
            this.leftChild = null;
            this.rightChild = null;
        }
        
        public static TreeNode getParent(TreeNode subTree, TreeNode element) {
            if (subTree == null)
                return null;
            if (subTree.leftChild == element || subTree.rightChild == element)
                return subTree;
            TreeNode p = null;
            // 遞歸左右子樹
            if ((p = getParent(subTree.leftChild, element)) != null)
                return p;
            else
                return getParent(subTree.rightChild, element);
        }

        public static TreeNode getLeftChildNode(TreeNode element) {
            return (element != null) ? element.leftChild : null;
        }

        public static TreeNode getRightChildNode(TreeNode element) {
            return (element != null) ? element.rightChild : null;
        }
        
        public static int height(TreeNode subTree) {
            if (subTree == null)
                return 0;// 遞歸結束:空樹高度爲0
            else {
                int i = height(subTree.leftChild);
                int j = height(subTree.rightChild);
                return (i < j) ? (j + 1) : (i + 1);
            }
        }
        
        public static int size(TreeNode subTree) {
            if (subTree == null) {
                return 0;
            } else {
                return 1 + size(subTree.leftChild) + size(subTree.rightChild);
            }
        }
        
        // 在釋放某個結點前, 該結點的左右子樹應該已經釋放, 因此應該採用後續遍歷
        public static void destroySubTree(TreeNode subTree) {
            // 刪除根爲subTree的子樹
            if (subTree != null) {
                destroySubTree(subTree.leftChild);
                destroySubTree(subTree.rightChild);
                // 刪除根結點
                subTree = null;
            }
        }
        
        
        public static void visted(TreeNode subTree) {
            System.out.println("data: " + subTree.data);
        }
        
        // 前序遍歷
        public static void preOrder(TreeNode subTree) {
            if (subTree != null) {
                visted(subTree);
                preOrder(subTree.leftChild);
                preOrder(subTree.rightChild);
            }
        }

        // 中序遍歷
        public static void inOrder(TreeNode subTree) {
            if (subTree != null) {
                inOrder(subTree.leftChild);
                visted(subTree);
                inOrder(subTree.rightChild);
            }
        }

        // 後續遍歷
        public static void postOrder(TreeNode subTree) {
            if (subTree != null) {
                postOrder(subTree.leftChild);
                postOrder(subTree.rightChild);
                visted(subTree);
            }
        }
        
        // 前序遍歷的非遞歸實現
        public static void nonRecPreOrder(TreeNode subTree) {
            Stack<TreeNode> stack = new Stack<TreeNode>();
            TreeNode node = subTree;
            while (node != null || stack.size() > 0) {
                if (node != null) {
                    visted(node);
                    stack.push(node);
                    node = node.leftChild;
                } else {
                    node = stack.pop();
                    node = node.rightChild;
                }
            }
        }

        // 中序遍歷的非遞歸實現
        public static void nonRecInOrder(TreeNode subTree) {
            Stack<TreeNode> stack = new Stack<TreeNode>();
            TreeNode node = subTree;
            while (node != null || stack.size() > 0) {
                // 存在左子樹
                if (node != null) {
                    stack.push(node);
                    node = node.leftChild;
                }
                else {
                    node = stack.pop();
                    visted(node);
                    node = node.rightChild;
                }
            }
        }

        // 後序遍歷的非遞歸實現
        public static void nonRecPostOrder(TreeNode subTree) {
            if (null == subTree) { //爲確保下面循環至少執行一次
                return;  
            }
            Stack<TreeNode> stack = new Stack<TreeNode>();
            TreeNode node = subTree;
            TreeNode lastVisited = subTree;
            while (true) {
                // 左路入棧
                while (node.leftChild != null) {
                    stack.push(node);    //第一次壓棧, 爲了訪問左路後退出
                    node = node.leftChild;
                }
                // 連續處理從右路返回的節點
                while (node.rightChild == null || node.rightChild == lastVisited) {
                    // 訪問並紀錄本次訪問節點
                    visted(node);
                    lastVisited = node;
                    if (stack.empty()) {
                        return;
                    }
                    node = stack.pop();
                }
                // 處理從左路返回的節點
                stack.push(node);  // 第二次壓棧, 爲了訪問右路後退出
                node = node.rightChild;
            }
        }
    }
    
    
    // 二叉搜索樹
    public void add(int data) {
        add(root, data);
    }
    
    public boolean contains(int data) {
        return contains(root, data);
    }
    
    public int minValue() {
        return findMin(root).data;
    }
    
    public int maxValue() {
        return findMax(root).data;
    }
    
    private TreeNode findMin(TreeNode subTree) {
        if (null == subTree) {
            return null;
        } else if (null == subTree.leftChild) {
            return subTree;
        }
        return findMin(subTree.leftChild);
    }

    private TreeNode findMax(TreeNode subTree) {
        if (null != subTree) {
            while (null != subTree.rightChild) {
                subTree = subTree.rightChild;
            }
        }
        return subTree;
    }
    // 添加節點進搜索樹
    private TreeNode add(TreeNode subTree, int data) {
        if (null == subTree) {
            return new TreeNode(data);
        } else if (data > subTree.data) {
            subTree.rightChild = add(subTree.rightChild, data);
            return subTree;
        } else if (data < subTree.data) {
            subTree.leftChild = add(subTree.leftChild, data);
            return subTree;
        } // 這裏限定搜索樹中元素不重複
        return subTree;
    }

    private boolean contains(TreeNode subTree, int data) {
        if (null == subTree) {
            return false;
        } else if (data > subTree.data) {
                return contains(subTree.rightChild, data);
        } else if (data < subTree.data){
                return contains(subTree.leftChild, data);
        } else {
            return true;
        }
    }
    
    private TreeNode remove(TreeNode subTree, int data) {
        if (null == subTree) {
            return null;
        } else if (data > subTree.data) {
            return remove(subTree.rightChild, data);
        } else if (data < subTree.data) {
            return remove(subTree.leftChild, data);
        } else if (null == subTree.leftChild || null == subTree.rightChild) {  //節點匹配, 只有一個孩子或沒有孩子
            return (subTree.leftChild != null) ? subTree.leftChild : subTree.rightChild; 
        } else {      //節點匹配, 有兩個孩子
            subTree.data = findMin(subTree.rightChild).data;
            subTree.rightChild = remove(subTree.rightChild, subTree.data);
            return subTree;
        }
    }
    
    // 測試
    public static void main(String[] args) {
        // 建立樹
        int[] values = new int[8];
        for (int i = 0; i < 8; i++) {
            int num = (int) (Math.random() * 15);
            if (!checkDup(values, num))
                values[i] = num;
            else
                i--;
        }
        System.out.println("generate Nums:" + Arrays.toString(values));

        BSTree tree = new BSTree(new TreeNode(values[0]));
        for (int i = 1; i < values.length; i++) {
            tree.add(values[i]);
        }

        System.out.println("樹高: " + TreeNode.height(tree.getRoot()));
        System.out.println("樹大小: " + TreeNode.size(tree.getRoot()));
        System.out.println("前序遍歷:");
        TreeNode.nonRecPreOrder(tree.getRoot());
        System.out.println("中序遍歷:");
        TreeNode.nonRecInOrder(tree.getRoot());
        System.out.println("後序遍歷:");
        TreeNode.nonRecPostOrder(tree.getRoot());
    }
    private static boolean checkDup(int[] arr, int value) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value)
                return true;
        }
        return false;
    }
    
}
複製代碼