Java教程

线索化二叉树

本文主要是介绍线索化二叉树,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

简介
在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。
n个结点的二叉链表中含有n+1 【公式 2n-(n-1)=n+1】 个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")
这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
一个结点的前一个结点,称为前驱结点,一个结点的后一个结点,称为后继结点.
代码
结点对象

class Node2 {
  int value;

  private int leftType;
  private int rightType;

  public Node2 parent;

  public Node2 getParent() {
    return parent;
  }

  public void setParent(Node2 parent) {
    this.parent = parent;
  }

  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 Node2(int value) {
    this.value = value;
  }

  private Node2 left;
  private Node2 right;

  public int getValue() {
    return value;
  }

  public void setValue(int value) {
    this.value = value;
  }


  public Node2 getLeft() {
    return left;
  }

  public void setLeft(Node2 left) {
    this.left = left;
  }

  public Node2 getRight() {
    return right;
  }

  public void setRight(Node2 right) {
    this.right = right;
  }

  @Override
  public String toString() {
    return "Node2{" +
            "value=" + value +
            '}';
  }

  /**
   * 如果添加的结点比父结点小,就添加到父结点的左节点,反之添加到父结点的右结点(二叉排序树)
   * @param node 添加的结点对象
   */
  public void add(Node2 node) {
    if (node == null) {
      return;
    }
    if (this.value > node.value) {
      if (this.left == null) {
        this.left = node;
      } else {
        this.left.add(node);
      }
    } else {
      if (this.right == null) {
        this.right = node;
      } else {
        this.right.add(node);
      }
    }
  }

}

class ThreadedBinaryTree {
  private Node2 root;

  private Node2 pre = null;

  public Node2 getRoot() {
    return root;
  }

  /**
   * 如果添加的结点比父结点小,就添加到父结点的左节点,反之添加到父结点的右结点(二叉排序树)
   * @param node 添加的结点对象
   */
  public void add(Node2 node) {
    if (root == null) {
      root = node;
    } else {
      root.add(node);
    }
  }
  //中序线索化
  public void threadedNodes(Node2 node) {
    if (node == null) {
      return;
    }
    threadedNodes(node.getLeft());
    if (node.getLeft() == null) {
      node.setLeft(pre);
      node.setLeftType(1);
    }

    if (pre != null && pre.getRight() == null) {
      pre.setRight(node);
      pre.setRightType(1);
    }
    pre = node;

    threadedNodes(node.getRight());
  }

  //中线索化二叉树遍历
  public void threadedList() {
      Node2 node = root;
      while (node != null) {
        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();
      }
  }

  //前序线索化
  public void preorder(Node2 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.getLeftType() == 0) {
     preorder(node.getLeft());
   }

   if (node.getRightType() == 0) {
     preorder(node.getRight());
   }
  }

  //遍历前序线索化二叉树
  public void preorderList() {
    Node2 node = root;
    while (node != null) {
      while (node.getLeftType() == 0) {
        System.out.println(node);
        node = node.getLeft();
      }

      System.out.println(node);

      while (node.getRightType() == 1) {
        node = node.getRight();
        System.out.println(node);
      }
      node = node.getRight();
    }
  }

  /**
   * 注意,后序遍历要设置每个结点的父结点!!!
   * @param node 开始的结点
   */
  //后序线索化二叉树
  public void postorder(Node2 node) {
    if (node == null) {
      return;
    }
    if (node.getLeftType() == 0) {
      postorder(node.getLeft());
    }

    if (node.getRightType() == 0) {
      postorder(node.getRight());
    }

    if (node.getLeft() == null) {
      node.setLeft(pre);
      node.setLeftType(1);
    }

    if (pre != null && pre.getRight() == null) {
      pre.setRight(node);
      pre.setRightType(1);
    }
    pre = node;
  }

  //后序线索化二叉树遍历
  public void postorderList() {
    Node2 node = root;
    while ( node != null && node.getLeftType() == 0 ) {
      node = node.getLeft();
    }
    while ( node != null ) {
      //右节点是线索
      if (node.getRightType() == 1) {
        System.out.print(node + ", ");
        pre = node;
        node = node.getRight();
      } else {
        //如果上个处理的节点是当前节点的右节点
        if (node.getRight() == pre) {
          System.out.print(node + ", ");
          if (node == root) {
            return;
          }
          pre = node;
          node = node.getParent();
        } else {    //如果从左节点的进入则找到有子树的最左节点
          node = node.getRight();
          while ( node != null && node.getLeftType() == 0 ) {
            node = node.getLeft();
          }
        }
      }
    }
  }

}

测试

   ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();
    int[] arr = {1,7,2,5,9,6};
    for (int i : arr) {
      threadedBinaryTree.add(new Node2(i));
    }
    threadedBinaryTree.threadedNodes(threadedBinaryTree.getRoot());
    threadedBinaryTree.threadedList();

这篇关于线索化二叉树的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!