线索化二叉树特点: (1)一个结点的前一个结点,称为前驱结点 (2)一个结点的后一个结点,成为后继结点 (3)n个结点的二叉链表中含有n+1(2n -(n-1) = n+1)个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针,这个指针成为“线索”。 (4)这种加上线索的二叉链表成为线索链表,相应的二叉树称为线索二叉树。根据线索性质的不同,线索二叉树可分为前序、中序、后序线索二叉树。 (5)线索链表解决了无法直接找到该结点在某种遍历序列中的前驱和后继结点的问题,解决了二叉链表找左、右孩子困难的问题。
思路分析:
(1)left指向左子树,也有可能指向前驱结点。 (2)Right指向的右子树,也有可能指向后继结点。遍历线索化二叉树:
由于线索化后,各个结点指向都有变化,因此原来的遍历方式不能够使用,这是需要用到新的方式遍历线索化二叉树,各个结点都可以通过线性方式遍历,不需用到递归方式,这样也提高了效率。!!!遍历的次序要与前面遍历的此序一致!
如图所示(中序线索化二叉树过程):
实现代码:
package com.struct.threadedbinarytree; public class ThreadedBinaryTreeDemo { public static void main(String[] args) { Node root = new Node(1, "Tom"); Node node2 = new Node(3, "Jack"); Node node3 = new Node(6, "Lucy"); Node node4 = new Node(8, "Flora"); Node node5 = new Node(10, "Smith"); Node node6 = new Node(14, "Mary"); root.setLeft(node2); root.setRight(node3); node2.setLeft(node4); node2.setRight(node5); node3.setLeft(node6); BinaryTree t1 = new BinaryTree(); t1.setRoot(root); t1.infixThreadedTrees(root); t1.infixOrderThreadedTrees(); } } class BinaryTree { private Node root;//定义根结点 private Node pre = null;//定义一个前驱结点 public Node getRoot() { return root; } public void setRoot(Node root) { this.root = root; } //中序线索化二叉树方法 public void infixThreadedTrees(Node node) { //此时为空,不能线索化 if (node == null) return; //线索化左子树 infixThreadedTrees(node.getLeft()); //线索化当前结点 //处理前驱结点 if (node.getLeft() == null) { //让当前结点的左指针指向前驱结点 node.setLeft(pre); node.setLeftType(1); } //处理后继结点,使用下一次线索化的node保留的pre(前驱结点)来处理 if (pre != null && pre.getRight() == null)//此时pre是下一次线索化node的前驱结点 { //让前驱结点的右指针指向当前结点 pre.setRight(node); pre.setRightType(1); } //处理完一个结点后,让当前结点指向下一个结点的前驱结点 pre = node; //线索化右子树 infixThreadedTrees(node.getRight()); } //中序遍历线索化二叉树 public void infixOrderThreadedTrees() { Node node = root;//定义一个结点,接收root结点,从root结点开始遍历 while (node != null)//当node不为空时,一直遍历 { while (node.getLeftType() == 0)//寻找node有前驱结点的结点 node = node.getLeft(); System.out.println(node);//输出此结点 while (node.getRightType() == 1)//把该结点的后继结点全部输出出来 { node = node.getRight(); System.out.println(node); } //替换node,不然会出现死循环 node = node.getRight(); } } } //创建Node类 //定义节点类 class Node { private int no;//定义节点编号 private String name;//定义节点名称 private Node left;//定义节点左子节点 private Node right;//定义节点右子节点 private int leftType;//0表示指向左子树,1表示指向前驱结点 private int rightType;//0表示指向右子树,1表示指向后继结点 public Node(int no, String name) { this.no = no; this.name = name; } 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 int getNo() { return no; } public void setNo(int no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Node getLeft() { return left; } public void setLeft(Node left) { this.left = left; } public Node getRight() { return right; } public void setRight(Node right) { this.right = right; } @Override public String toString() { return "Node{" + "no=" + no + ", name='" + name + '\'' + '}'; } }