樹的父節點表示法及其Java實現
阿新 • • 發佈:2019-01-06
樹中除了根節點之外,每個節點都有且僅有一個父節點,為了記錄樹中節點與節點之間的父子關係,可以為每個節點增加一個parent域,用以記錄該節點的父節點。
對於下圖中的樹:
可以用下表來儲存:
由此可見,只要用一個節點陣列來儲存樹中的每個節點,並讓每個節點記錄其父節點在陣列中的索引即可。
Java實現程式碼
package com.liuhao.DataStructures; import java.util.ArrayList; import java.util.List; public class TreeParent<E> { public static class Node<T> { T data; int parent;// 記錄父節點的位置 public Node() { } public Node(T data) { this.data = data; } public Node(T data, int parent) { this.data = data; this.parent = parent; } public String toString() { return "TreeParent$Node[data=" + data + ", parent=" + parent + "]"; } } private final int DEFAULT_TREE_SIZE = 100; private int treeSize = 0; // 使用一個Node[]陣列來記錄該樹的所有節點 private Node<E>[] nodes; // 記錄節點數 private int nodeNums; // 以指定節點建立樹 public TreeParent(E data) { this.treeSize = DEFAULT_TREE_SIZE; this.nodes = new Node[treeSize]; nodes[0] = new Node<E>(data, -1); nodeNums++; } // 以指定根節點、指定treeSize建立樹 public TreeParent(E data, int treeSize) { this.treeSize = treeSize; this.nodes = new Node[treeSize]; nodes[0] = new Node<E>(data, -1); nodeNums++; } // 判斷是否為空 public boolean isEmpty() { // 跟節點是否為空 return nodes[0] == null; } // 返回包含指定節點的索引位置 public int pos(Node<E> node) { for (int i = 0; i < treeSize; i++) { if (nodes[i] == node) { return i; } } return -1; } // 為指定節點新增子節點 public void addNode(E data, Node<E> parent) { for (int i = 0; i < treeSize; i++) { // 找到陣列中第一個為null的節點,用該節點儲存新節點 if (nodes[i] == null) { nodes[i] = new Node<E>(data, this.pos(parent)); nodeNums++; return; } } throw new RuntimeException("該樹已滿,無法新增新節點"); } // 獲取根節點 public Node<E> getRoot() { return nodes[0]; } // 獲取指定節點的父節點 public Node<E> getParent(Node<E> node) { // 每個節點記錄了其父節點的位置 return nodes[node.parent]; } // 獲取指定節點的子節點 public List<Node<E>> getChildren(Node<E> node) { List<Node<E>> list = new ArrayList<Node<E>>(); for (int i = 0; i < treeSize; i++) { if (nodes[i] != null && nodes[i].parent == this.pos(node)) { list.add(nodes[i]); } } return list; } // 獲取樹的深度 public int getDeep() { int max = 0; for (int i = 0; i < treeSize && nodes[i] != null; i++) { //初始化當前節點的深度 int def = 1; //m記錄當前節點的父節點的位置 int m = nodes[i].parent; while(m != -1 && nodes[m] != null){ //繼續向上搜尋父節點 m = nodes[m].parent; def++; } if(def > max){ max = def; } } return max; } //刪除指定節點的子樹 public void removeChildren(Node<E> node){ for (int i = 0; i < treeSize; i++) { if (nodes[i] != null && nodes[i].parent == this.pos(node)) { nodes[i] = null; nodeNums--; } } } }
測試程式碼:
package com.liuhao.test; import java.util.List; import org.junit.Test; import com.liuhao.DataStructures.TreeParent; import com.liuhao.DataStructures.TreeParent.Node; public class TreeParentTest { @Test public void test() { TreeParent<String> tree = new TreeParent<String>("root"); Node<String> root = tree.getRoot(); System.out.println("根節點:" + root); tree.addNode("節點1", root); tree.addNode("節點2", root); System.out.println("樹的深度:" + tree.getDeep()); List<Node<String>> nodes = tree.getChildren(root); System.out.println("根節點的第一個子節點:" + nodes.get(0)); tree.addNode("節點3", nodes.get(0)); System.out.println("樹的深度:" + tree.getDeep()); tree.removeChildren(root); System.out.println("根節點的第一個子節點:" + nodes.get(0)); System.out.println("樹的深度:" + tree.getDeep()); } }
通過上面的程式可以看出,父節點表示法可以方便的找出每個節點 的父節點,但是子節點的查詢很麻煩,需要遍歷整個樹。
您的關注是我堅持寫作的動力,如果覺得有用,歡迎關注我的微信,海量學習資源免費送!