1、順序存儲:採用數組來記錄二叉樹的全部節點。java
public class ArrayBinTree<T> { private final int DEFAULT_SIZE = 8; // 數組記錄該樹的全部節點 private Object[] datas; // 保存該樹的深度 private int deep; private int arraySize; // 以默認深度來建立二叉樹 public ArrayBinTree() { this.deep = DEFAULT_SIZE; this.arraySize = (int)Math.pow(2, deep) - 1; this.datas = new Object[arraySize]; } // 以指定深度來建立二叉樹 public ArrayBinTree(int deep) { this.deep = deep; this.arraySize = (int)Math.pow(2, deep) - 1; this.datas = new Object[arraySize]; } // 以指定深度、根節點建立二叉樹 public ArrayBinTree(int deep, T data) { this.deep = deep; this.arraySize = (int)Math.pow(2, deep) - 1; this.datas = new Object[arraySize]; datas[0] = data; } /** * 爲指定節點添加子節點 * @param index 須要添加子節點的父節點索引 * @param data 新子節點的數據 * @param left 是否爲左節點 */ public void addNode(int index, T data, boolean left) { if (datas[index] == null) { throw new RuntimeException(index + "節點爲空,不能添加子節點"); } if (2 * index + 1 >= arraySize) { throw new RuntimeException("樹底層的數組已滿,樹越界異常"); } if (left) { datas[2 * index + 1] = data; } else { datas[2 * index + 2] = data; } } // 判斷二叉樹是否爲空 public boolean empty() { // 根據根元素來判斷二叉樹是否爲空 return datas[0] == null; } // 返回根節點 public T root() { if (empty()) { throw new RuntimeException("樹爲空,沒法返回根節點"); } return (T)datas[0]; } // 返回指定節點(非根節點)的父節點 public T parent(int index) { if (index == 0) { throw new RuntimeException("根節點沒有父節點"); } return (T)datas[(index - 1) / 2]; } // 返回指定節點(非葉子)的左子節點,當左子節點不存在時返回null public T left(int index) { if (2 * index + 1 >= arraySize) { throw new RuntimeException(index + "節點爲葉子節點,沒有左子節點"); } return datas[index * 2 + 1] == null? null : (T)datas[index * 2 + 1]; } // 返回該二叉樹的深度 public int deep(int index) { return deep; } // 返回指定節點的位置 public int pos(T data) { // 該循環實際上就是按廣度遍從來搜索每一個節點 for (int i = 0; i < arraySize; i++) { if (datas[i] == data) { return i; } } return -1; } public String toString() { return java.util.Arrays.toString(datas); } }
2、二叉鏈表存儲:每一個節點保留一個left、rigth域,分別指向其左、右子節點。node
public class TwoLinkBinTree<E> { public static class TreeNode { private Object data; private TreeNode left; private TreeNode right; public TreeNode() { } public TreeNode(Object data) { this.data = data; } public TreeNode(Object data, TreeNode left, TreeNode right) { this.data = data; this.left = left; this.right = right; } } private TreeNode root; // 以默認構造器來建立二叉樹 public TwoLinkBinTree() { this.root = new TreeNode(); } // 以指定根元素來建立二叉樹 public TwoLinkBinTree(E data) { this.root = new TreeNode(data); } /** * 爲指定節點添加子節點 * @param parent 須要添加子節點的父節點的索引 * @param data 新子節點的數據 * @param left 是否爲左節點 * @return 新增的節點 */ public TreeNode addNode(TreeNode parent, E data, boolean left) { if (parent == null) { throw new RuntimeException(parent + "節點爲空,沒法添加子節點"); } if (left && parent.left != null) { throw new RuntimeException(parent + "節點已有左節點,沒法添加左節點"); } if (!left && parent.right != null) { throw new RuntimeException(parent + "節點已有右節點,沒法添加右節點"); } TreeNode newNode = new TreeNode(data); if (left) { parent.left = newNode; } else { parent.right = newNode; } return newNode; } // 判斷二叉樹是否爲空 public boolean empty() { // 根據根元素來判斷二叉樹是否爲空 return root.data == null; } // 返回根節點 public TreeNode root() { if (empty()) { throw new RuntimeException("樹爲空,沒法返回根節點"); } return root; } // 返回指定節點(非根節點)的父節點 public E parent(TreeNode node) { // 對於二叉鏈表存儲法,若是要訪問指定節點的父節點必須遍歷二叉樹 return null; } // 返回指定節點(非葉子)的左子節點,當左子節點不存在時返回null public E leftChild(TreeNode parent) { if (parent == null) { throw new RuntimeException(parent + "節點爲空,無左子節點"); } return parent.left == null ? null : (E)parent.left.data; } // 返回指定節點(非葉子)的右子節點。當右子節點不存在時返回null public E rightChild(TreeNode parent) { if (parent == null) { throw new RuntimeException(parent + "節點爲空,無右子節點"); } return parent.right == null ? null : (E)parent.right.data; } // 二叉樹的深度 public int deep() { // 獲取該樹的深度 deep(root); } // 遞歸方法:每顆子樹的深度爲其全部子樹的最大深度 + 1 private int deep(TreeNode node) { if (node == null) { return 0; } if (node.right == null && node.left == null) { return 1; } else { int leftDeep = deep(node.left); int rightDeep = deep(node.right); int max = leftDeep > rightDeep? leftDeep : rightDeep; return max + 1; } } }
3、三叉鏈表存儲:每一個節點保留一個left、right、parent域,分別指向其左、右子節點和父節點。數組
public class ThreeLinkBinTree<E> { public static class TreeNode { private Object data; private TreeNode parent; private TreeNode left; private TreeNode right; public TreeNode() { } public TreeNode(Object data) { this.data = data; } public TreeNode(Object data, TreeNode parent, TreeNode left, TreeNode right) { this.data = data; this.parent = parent; this.left = left; this.right = right; } } private TreeNode root; // 以默認構造器來建立二叉樹 public ThreeLinkBinTree() { root = new TreeNode(); } // 以指定根元素來建立二叉樹 public ThreeLinkBinTree(E data) { root = new TreeNode(data); } /** * 爲指定節點添加子節點 * @param parent 須要添加子節點的父節點的索引 * @param data 新子節點的數據 * @param left 是否爲左節點 * @return 新增的節點 */ public TreeNode addNode(TreeNode parent, E data, boolean left) { if (parent == null) { throw new RuntimeException(parent + "節點爲空,沒法添加子節點"); } if (left && parent.left != null) { throw new RuntimeException(parent + "節點左節點不爲空,沒法添加左子節點"); } if (!left && parent.right != null) { throw new RuntimeException(parent + "節點右節點不爲空,沒法添加右子節點"); } TreeNode newNode = new TreeNode(data); if (left) { parent.left = newNode; } else { parent.right = newNode; } newNode.parent = parent; return newNode; } // 判斷二叉樹是否爲空 public boolean empty() { // 根據根元素來判斷二叉樹是否爲空 return root.data == null; } // 返回根節點 public TreeNode root() { if (empty()) { throw new RuntimeException("根節點爲空"); } return root; } // 返回指定節點(非根節點)的父節點 public E parent(TreeNode node) { return (E)node.parent.data; } // 返回指定節點(非葉子)的左子節點。當左子節點不存在時返回null public E leftChild(TreeNode parent) { if (parent == null) { throw new RuntimeException(parent + "節點爲空,無左子節點"); } return parent.left == null ? null:(E)parent.left.data; } // 返回指定節點(非葉子)的右子節點。當右子節點不存在時返回null public E rightChild(TreeNode parent) { if (parent == null) { throw new RuntimeException(parent + "節點爲空,無左子節點"); } return parent.right == null ? null : (E)parent.right.data; } // 返回該二叉樹的深度 public int deep() { // 獲取該樹的深度 deep(root); } // 遞歸方法:每顆子樹的深度爲其全部子樹的最大深度 + 1 private int deep(TreeNode node) { if (node == null) { return 0; } if (node.left == null && node.right == null) { return 1; } else { int leftDeep = deep(node.left); int rightDeep = deep(node.right); int max = leftDeep > rightDeep? leftDeep : rightDeep; return max + 1; } } }
public class BinTreeTest { public static void main(String[] args) { ArrayBinTree<String> binTree = new ArrayBinTree<String>(4, "根"); binTree.addNode(0, "第二層右子節點", false); binTree.addNode(2, "第三層右子節點", false); binTree.addNode(6, "第四層右子節點", false); System.out.println("【順序存儲】二叉樹:" + binTree.toString()); TwoLinkBinTree<String> binTree2 = new TwoLinkBinTree<String>("根節點"); TwoLinkBinTree.TreeNode tn1 = binTree2.addNode(binTree2.root(), "第二層左節點", true); TwoLinkBinTree.TreeNode tn2 = binTree2.addNode(binTree2.root(), "第二層右節點", false); TwoLinkBinTree.TreeNode tn3 = binTree2.addNode(tn2, "第三層左節點", true); TwoLinkBinTree.TreeNode tn4 = binTree2.addNode(tn2, "第三層右節點", false); TwoLinkBinTree.TreeNode tn5 = binTree2.addNode(tn3, "第四層左節點", true); System.out.println("tn2的左子節點:" + binTree2.leftChild(tn2)); System.out.println("tn2的右子節點:" + binTree2.rightChild(tn2)); System.out.println("【二叉鏈表存儲】樹深度:" + binTree2.deep()); ThreeLinkBinTree<String> binTree3 = new ThreeLinkBinTree<String>("根節點"); ThreeLinkBinTree.TreeNode ttn1 = binTree3.addNode(binTree3.root(), "第二層左節點", true); ThreeLinkBinTree.TreeNode ttn2 = binTree3.addNode(binTree3.root(), "第二層右節點", false); ThreeLinkBinTree.TreeNode ttn3 = binTree3.addNode(ttn2, "第三層左節點", true); ThreeLinkBinTree.TreeNode ttn4 = binTree3.addNode(ttn2, "第三層右節點", false); ThreeLinkBinTree.TreeNode ttn5 = binTree3.addNode(ttn3, "第四層左節點", true); System.out.println("tn2的左子節點:" + binTree3.leftChild(ttn2)); System.out.println("tn2的右子節點:" + binTree3.rightChild(ttn2)); System.out.println("tn2的父子節點:" + binTree3.parent(ttn2)); System.out.println("【三叉鏈表存儲】樹深度:" + binTree3.deep()); } }