1. 程式人生 > 其它 >java--演算法--線索化二叉樹

java--演算法--線索化二叉樹

  1. 線索化二叉樹的介紹:
    1. 按照某種遍歷方式順序存放到陣列中:[0,1,2,3,4,5,6]:則1的前驅節點時0後繼節點時2
  2. 線索二叉樹的線索化程式碼實現:

    1. package com.model.tree;
      
      /**
       * @Description:測試類
       * @Author: 張紫韓
       * @Crete 2021/7/14 9:39
       * 線索化二叉樹的程式碼實現
       */
      public class TreeDemo03 {
          public static void main(String[] args) {
              HeroNode node1 = new HeroNode(1, "a");
              HeroNode node2 
      = new HeroNode(3, "b"); HeroNode node3 = new HeroNode(6, "c"); HeroNode node4 = new HeroNode(8, "d"); HeroNode node5 = new HeroNode(10, "e"); HeroNode node6 = new HeroNode(14, "f"); node1.setLeft(node2); node1.setRight(node3); node2.setLeft(node4); node2.setRight(node5); node3.setLeft(node6); ThreadedBinaryTree tree
      = new ThreadedBinaryTree(node1); tree.threadedNode(); System.out.println(node5.getLeft()); System.out.println(node5.getRightType()); } } class ThreadedBinaryTree { public HeroNode root; //第一個進行線索化的節點的前驅就是null private HeroNode pre=null; public ThreadedBinaryTree(HeroNode root) {
      this.root = root; } public ThreadedBinaryTree() { } public HeroNode getRoot() { return root; } public void setRoot(HeroNode root) { this.root = root; } public void threadedNode(){threadedNode(root);} // 編寫中中序化線索樹 public void threadedNode(HeroNode node){ if (node==null){ return; }else { // 線索化左子樹 threadedNode(node.getLeft()); // 線索化當前節點 if (node.getLeft()==null){ node.setLeft(pre); node.setLeftType(1); } //當pre移動到node節點是,再對node的右指標進行處理 if (pre!=null&&pre.getRight()==null){ pre.setRight(node); pre.setRightType(1); } pre=node; // 線索化右子樹 threadedNode(node.getRight()); } } } class HeroNode { private int id; private String name; private HeroNode left; private HeroNode right; //指定做指標事 是指向左右子樹還是執行前驅或後繼節點,如果是0則表示是字數如果是是1則表示指向前驅和後繼 private int leftType; private int rightType; public HeroNode(int id, String name, HeroNode left, HeroNode right) { this.id = id; this.name = name; this.left = left; this.right = right; } 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; } @Override public String toString() { return "Node{" + "id=" + id + ", 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 HeroNode getLeft() { return left; } public void setLeft(HeroNode left) { this.left = left; } public HeroNode getRight() { return right; } public void setRight(HeroNode right) { this.right = right; } public HeroNode() { } public HeroNode(int id, String name) { this.id = id; this.name = name; } public void preOrder(){ } }
  3. 線索化二叉樹的遍歷:

    1. package com.model.tree;
      
      /**
       * @Description:測試類
       * @Author: 張紫韓
       * @Crete 2021/7/14 9:39
       * 線索化二叉樹的程式碼實現
       */
      public class TreeDemo03 {
          public static void main(String[] args) {
              HeroNode node1 = new HeroNode(1, "a");
              HeroNode node2 = new HeroNode(3, "b");
              HeroNode node3 = new HeroNode(6, "c");
              HeroNode node4 = new HeroNode(8, "d");
              HeroNode node5 = new HeroNode(10, "e");
              HeroNode node6 = new HeroNode(14, "f");
              node1.setLeft(node2);
              node1.setRight(node3);
              node2.setLeft(node4);
              node2.setRight(node5);
              node3.setLeft(node6);
              ThreadedBinaryTree tree = new ThreadedBinaryTree(node1);
      //        中序線索化
              tree.threadedNode();
              System.out.println(node5.getLeft());
              System.out.println(node5.getRightType());
              tree.preOrder();
              System.out.println("---------------------");
              tree.preOrder03();
      
      //        先序線索化
      //
      //        tree.threadedInfix();
      //        System.out.println(node4.getLeft());
      //        System.out.println(node4.getRight());
      
      
          }
      }
      
      class ThreadedBinaryTree {
          public HeroNode root;
          //第一個進行線索化的節點的前驅就是null
          private HeroNode pre = null;
      
          public ThreadedBinaryTree(HeroNode root) {
              this.root = root;
          }
      
          public ThreadedBinaryTree() {
          }
      
          public HeroNode getRoot() {
              return root;
          }
      
          public void setRoot(HeroNode root) {
              this.root = root;
          }
      
          public void threadedNode() {
              threadedNode(root);
          }
      
      //    public void threadedInfix() {
      //        threadedInfix(root);
      //    }
      //        編寫中中序化線索樹
      
          public void threadedNode(HeroNode node) {
              if (node == null) {
                  return;
              } else {
      //        線索化左子樹
                  threadedNode(node.getLeft());
      //        線索化當前節點
                  if (node.getLeft() == null) {
                      node.setLeft(pre);
                      node.setLeftType(1);
                  }
                  //當pre移動到node節點是,再對node的右指標進行處理
                  if (pre != null && pre.getRight() == null) {
                      pre.setRight(node);
                      pre.setRightType(1);
                  }
                  pre = node;
      //        線索化右子樹
                  threadedNode(node.getRight());
              }
          }
      
      //    //    先序遍歷線索化
      //    public void threadedInfix(HeroNode node) {
      //        if (node == null) {
      //            return;
      //        }
      ////        線索化當前節點
      //        if (node.getLeft() == null) {
      //            node.setLeft(pre);
      //            node.setLeftType(1);
      //        }
      //        if (pre != null && pre.getRight() == null) {
      //            pre.setRight(node);
      //            pre.setRightType(1);
      //        }
      //
      //        pre = node;
      ////       序列化左子樹
      //        if (node.getLeft()!=null){threadedInfix(node.getLeft());}
      ////        序列化右子樹
      //        if (node.getRight()!=null){threadedInfix(node.getRight());}
      //        
      //    }
      
          public void preOrder() {
              root.preOrder();
          }
      
          //利用線索化進行遍歷《
      //    線索化二叉樹,線索化的節點,指向的下一個節點就是中序遍歷的下一個節點,
      //    但是如果沒有線索化的節點,並不是中序遍歷的節點
      //    我們可以根據中序遍歷找到第一個節點,根據線索化,right 向後遍歷,但是需要判斷後面的是 線索化的還是普通的指向其右子樹
      //    如果本節點的right 是線索化的我們可以直接 進行輸出,因為他就是中序遍歷的下一個節點,如果本節點的right指向的是其右子樹
      //    我們子需要重新找到這個右子樹的第一個節點,自此進行上述遍歷
          public void preOrder02() {
              HeroNode temp = root;
      //       找到第一個節點,利用線索化向後一定,遍歷所有的元素
              while (temp != null) {
                  while (temp.getLeftType() == 0) {
                      temp = temp.getLeft();
                  }
      //            找到第一個節點
                  System.out.println(temp);
      
                  while (temp.getRightType() == 1) {
                      temp = temp.getRight();
                      System.out.println(temp);
                  }
                  temp = temp.getRight();
              }
          }
      
          public void preOrder03() {
              HeroNode temp = root;
              while (temp != null) {
      //      1.得到這個樹中序遍歷的第一個節點(第一次是整個樹,第二次就是某個節點的子樹)
                  while (temp.getLeftType() == 0) {
                      temp = temp.getLeft();
                  }
      //       2.列印第一個節點
                  System.out.println(temp);
      //        3. 根據節點的線索化判斷其右節點是其子樹還是線索化的下一節點
                  while (temp.getRightType() == 1) {
      //                說明temp的右節點就是一個線索化的節點,就是中序遍歷的下一節點
                      temp = temp.getRight();
                      System.out.println(temp);
                  }
      //         4.跳出迴圈說明其右指標指向的是一個右子樹
                  temp = temp.getRight();//執行右子樹重複上敘操作
      
              }
      
          }
      
      
      }
      
      class HeroNode {
          private int id;
          private String name;
          private HeroNode left;
          private HeroNode right;
      
          //指定做指標事 是指向左右子樹還是執行前驅或後繼節點,如果是0則表示是字數如果是是1則表示指向前驅和後繼
          private int leftType;
          private int rightType;
      
          public HeroNode(int id, String name, HeroNode left, HeroNode right) {
              this.id = id;
              this.name = name;
              this.left = left;
              this.right = right;
          }
      
          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;
          }
      
          @Override
          public String toString() {
              return "Node{" +
                      "id=" + id +
                      ", 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 HeroNode getLeft() {
              return left;
          }
      
          public void setLeft(HeroNode left) {
              this.left = left;
          }
      
          public HeroNode getRight() {
              return right;
          }
      
          public void setRight(HeroNode right) {
              this.right = right;
          }
      
          public HeroNode() {
          }
      
          public HeroNode(int id, String name) {
              this.id = id;
              this.name = name;
          }
      
          public void preOrder() {
              if (this == null) {
                  return;
              } else {
                  if (this.left != null && this.leftType == 0) {
                      this.left.preOrder();
                  }
                  System.out.println(this);
                  if (this.right != null && this.leftType == 0) {
                      this.right.preOrder();
                  }
              }
      
          }
      
      }