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; } }