遍歷中序線索樹
阿新 • • 發佈:2021-08-10
13.3.1 遍歷中序線索樹
說明:對前面的中序先躲的二叉樹,進行遍歷
分析:因為線索化後,各個結點指向有變化,因此原來的遍歷方式不能使用這時需要使用新的方式遍歷線索化二叉樹,各個節點可以通過線性方式遍歷。因此無需使用遞迴方式,這樣也提高了便利的效率。 遍歷的次序應當和中序遍歷保持一致
package tree.threadedbinarytree; public class ThreadedBinaryTreeDemo { public static void main(String[] args) { // 測試 把中序線索二叉樹 Node1 root = new Node1(1, "12"); Node1 node2 = new Node1(3, "13"); Node1 node3 = new Node1(6, "16"); Node1 node4 = new Node1(8, "18"); Node1 node5 = new Node1(10, "114"); Node1 node6 = new Node1(14, "114"); // 二叉樹後面要遞迴建立,現在手動建立 root.setLeft(node2); root.setRight(node3); node2.setLeft(node4); node2.setRight(node5); node3.setLeft(node6); // 測試中序線索化 infixThreadedBinaryTree infixThreadedBinaryTree = new infixThreadedBinaryTree(); infixThreadedBinaryTree.setRoot(root); infixThreadedBinaryTree.threadeNodes(); // 測試:以10號結點為測試 Node1 leftNode = node5.getLeft(); Node1 rightNode = node5.getRight(); System.out.println("10號結點的前驅結點時:" + leftNode); System.out.println("10號結點的後繼結點" + rightNode); // 使用線索化二叉樹後,能夠使用原來的遍歷方法 System.out.println("使用線索化的方式遍歷 線索化二叉樹"); infixThreadedBinaryTree.infixThreadedList(); // // 測試前序線索化 // infixThreadedBinaryTree.setRoot(root); // infixThreadedBinaryTree.postNodes(); // // // 測試:以10號結點為測試 // Node1 leftNode = node5.getLeft(); // Node1 rightNode = node5.getRight(); // System.out.println("10號結點的前驅結點時:" + leftNode); // System.out.println("10號結點的後繼結點" + rightNode); } } // 線索化二叉樹 實現了線索化功能的二叉樹 class infixThreadedBinaryTree{ private Node1 root; // 為了實現線索化,需要建立要給指向當前節點的前驅結點的指標 // 在遞迴的進行線索時,pre 總是保留一個結點 private Node1 pre = null; // 遍歷中序線索二叉樹 public void infixThreadedList(){ // 定義一個變數,儲存當前遍歷的節點,從root開始 Node1 node = root; while(node != null){ // 迴圈的找到leftType == 1的節點,第一個找到的就是8 // 後面隨著遍歷node會變化, // 因為當leftType == 1時,說明該節點時按照線索化處理後的有效節點 while (node.getLeftType() == 0){ node = node.getLeft(); } // 列印當前節點 System.out.println(node); // 如果當前節點的右指標指向的是後繼結點,就一直輸出 while (node.getRightType() == 1){ // 說明當前節點指向後繼結點 // 獲取當前節點的後繼結點 node = node.getRight(); System.out.println(node); } // 替換這個便利的節點 node = node.getRight(); } } // 過載一把threadeNodes方法 public void threadeNodes(){ this.threadedNodes(root); } // 編寫二叉樹進行中序線索化的方法 /** * * @param node 就是當前需要線索化的結點 */ public void threadedNodes(Node1 node){ // 如果 node == null,不能進行線索化 if (node == null){ return; } // 1. 先線索化左子樹 threadedNodes(node.getLeft()); // 2. 線索化當前結點 // 2.1 先處理當前節點的前驅結點 if (node.getLeft() == null){ // 讓當前節點的左指標指向前驅結點 node.setLeft(pre); // 修改當前節點的左指標的型別,指向前驅結點 node.setLeftType(1); } // 2.2 處理當前節點的後繼結點 if (pre != null && pre.getRight() == null){ // 讓前驅結點的右指標指向當前結點 pre.setRight(node); // 修改前驅結點的右指標型別 pre.setRightType(1); } // 沒處理一個節點後,讓當前結點時下一個節點的前驅結點 pre = node; // 3. 再線索化右子樹 threadedNodes(node.getRight()); } } // 先建立節點 class Node1{ private int id; private String name; private Node1 left; private Node1 right; // 說明 // 1. 如果leftType == 0 表示的指向的是左子樹,如果1則表示指向前驅結點 // 2. 如果rightType == 0 表示指向的是右子樹,如果1則表示指向的是後繼結點 private int leftType; private int rightType; public int getLeftType() { return leftType; } public void setLeftType(int leftType) { this.leftType = leftType; } public int getRightType() { return rightType; } public void setRightType(int rightType) { this.rightType = rightType; } public Node1(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Node1 getLeft() { return left; } public void setLeft(Node1 left) { this.left = left; } public Node1 getRight() { return right; } public void setRight(Node1 right) { this.right = right; } @Override public String toString() { return "Node1{" + "id=" + id + ", name='" + name + '\'' + '}'; } }