微信搜索:碼農StayUp
主頁地址:https://gozhuyinglong.github.io
源碼分享:https://github.com/gozhuyinglong/blog-demosjava
二叉樹是一棵特殊的樹,其結構簡單但很重要。二叉樹的特色是每一個節點最多有兩棵子樹,而且有左右之分。node
滿二叉樹
若是一棵二叉樹的全部葉子節點都在最後一層,稱爲滿二叉樹。滿二叉樹的結點總數 = $2^n-1$ (n爲層數)。以下圖二叉是的層數爲3,其結點總數爲$2^3-1=7$
git
徹底二叉樹
一棵深度爲k的有n個結點的二叉樹,對樹中的節點按從上至下、從左到右的順序進行編號,若是編號爲i(1≤i≤n)的結點與滿二叉樹中編號爲i的結點在二叉樹中的位置相同,則這棵二叉樹稱爲徹底二叉樹。顯示下圖中a和b是徹底二叉樹,而c不是徹底二叉樹(倒數第二層不連續)github
小結:一棵滿二叉樹必定是一棵徹底二叉樹;而一棵徹底二叉樹不必定是滿二叉樹。微信
二叉樹是遞歸定義的,其節點有左右子樹之分,邏輯上二叉樹有五種基本形態:app
小結:用輸出父節點的順序來判斷是前序、中序仍是後序遍歷post
經過Java代碼實現下圖中二叉樹,並經過三種方式遍歷該二叉樹(前序、中序、後序)。ui
Node
類爲節點類,其中element表示節點元素,left爲左子節點,right爲右子節點。this
BinaryTree
類實現二叉樹的具體操做,如前序遍歷、中序遍歷、後序遍歷。.net
public class BinaryTreeDemo { public static void main(String[] args) { BinaryTree tree = new BinaryTree(); Node a = new Node("A"); Node b = new Node("B"); Node c = new Node("C"); Node d = new Node("D"); Node e = new Node("E"); Node f = new Node("F"); Node g = new Node("G"); Node h = new Node("H"); Node i = new Node("I"); tree.setRoot(a); a.left = b; a.right = c; b.left = d; b.right = e; d.left = h; c.left = f; c.right = g; g.right = i; System.out.println("---------------前序遍歷"); tree.preOrder(); System.out.println("---------------中序遍歷"); tree.inOrder(); System.out.println("---------------後序遍歷"); tree.postOrder(); } private static class BinaryTree { private Node root; // 根 public void setRoot(Node root) { this.root = root; } /** * 前序遍歷 */ public void preOrder() { preOrder(root, 0); } /** * 前序遍歷 * * @param node * @param depth 層級(用於輔助輸出) */ public void preOrder(Node node, int depth) { if (node == null) { return; } // 輸出當前節點 this.print(node, depth); // 遞歸左子節點 if (node.left != null) { preOrder(node.left, depth + 1); } // 遞歸右子節點 if (node.right != null) { preOrder(node.right, depth + 1); } } /** * 中序遍歷 */ public void inOrder() { inOrder(root, 0); } /** * 中序遍歷 * * @param node * @param depth 層級(用於輔助輸出) */ public void inOrder(Node node, int depth) { if (node == null) { return; } // 遞歸左子節點 if (node.left != null) { inOrder(node.left, depth + 1); } // 輸出當前節點 this.print(node, depth); // 遞歸右子節點 if (node.right != null) { inOrder(node.right, depth + 1); } } /** * 後序遍歷 */ public void postOrder() { postOrder(root, 0); } /** * 後序遍歷 * * @param node * @param depth 層級(用於輔助輸出) */ public void postOrder(Node node, int depth) { if (node == null) { return; } // 遞歸左子節點 if (node.left != null) { postOrder(node.left, depth + 1); } // 遞歸右子節點 if (node.right != null) { postOrder(node.right, depth + 1); } // 輸出當前節點 this.print(node, depth); } /** * 按照層級輸出節點元素 * * @param node * @param depth */ private void print(Node node, int depth) { StringBuilder t = new StringBuilder(); for (int i = 0; i < depth; i++) { t.append("\t"); } System.out.printf("%s%s\n", t.toString(), node.element); } } private static class Node { private final Object element; // 節點元素 private Node left; // 左子節點 private Node right; // 右子節點 public Node(Object element) { this.element = element; } } }
輸出結果:
---------------前序遍歷 A B D H E C F G I ---------------中序遍歷 H D B E A F C G I ---------------後序遍歷 H D E B F I G C A