为什么要线索化二叉树?
答:对于如下一颗二叉树, 中序遍历二叉树结果为4,2,5,1,3那么我想知道5前面的数是什么,就必须要先中序遍历一遍然后再去查询5前面的数字。那么如果我这样操作:对于左右子节点为null的节点,它的左节点指向前一个节点,右节点指向下一个节点,同时标记指针置为1,这样的话,我就可以直接知道中序遍历时5的前一个节点和后一个节点。
这个对二叉树的操作过程叫:线索化二叉树,可知有中序、前序、后序线索化二叉树的方法。得到的树为线索二叉树。
线索化二叉树时,一个节点的前一个节点,叫前驱节点。
线索化二叉树时,一个节点的后一个节点,叫后继节点
对上面二叉树的中序线索化的结果为:
前序线索化的结果为:
后序线索化的结果为:
(中序线索化二叉树以及中序后继遍历和中序前驱遍历)实现代码如下:
public class ThreadBinaryTree {
private static Node preNode;
static class Node{
int value;
Node left;
Node right;
boolean isLeftThread = false;
boolean isRightThread = false;
public Node(int value) {
this.value = value;
}
}
/**数组构建一棵完全二叉树
* @param arr:数组
* @param index:数组下标索引
* @return
*/
public static Node createBinaryTree(int[] arr, int index) {
Node node = null;
if(index < arr.length) {
node = new Node(arr[index]);
node.left = createBinaryTree(arr, index * 2 + 1);
node.right = createBinaryTree(arr, index * 2 + 2);
}
return node;
}
/**中序线索化二叉树
* @param node
*/
public static void middleThreadBinaryTree(Node node) {
if(node !=null) {
middleThreadBinaryTree(node.left);
//左指针为空,将左指针指向前一个节点
if(node.left ==null) {
node.left =preNode;
node.isLeftThread = true;
}
//前一个节点不为空,且前一个节点的右节点为空
if(preNode !=null&&preNode.right==null) {
preNode.right = node;
preNode.isRightThread = true;
}
preNode = node;
middleThreadBinaryTree(node.right);
}
}
//中序遍历线索二叉树,按照后继方式遍历
public static void middleListShow(Node node) {
System.out.println("哈哈哈");
//找到最左边的节点
while(node!=null&&!node.isLeftThread) {
node = node.left;
System.out.println(node.value);
}
System.out.println("哈哈哈");
while(node !=null) {
System.out.print(node.value +" ");
//判断node的左子树是否为空
if(node.isRightThread) {
node = node.right;
}else {
//如果node的左节点不为空,找最左边的节点
node = node.right;
while(node !=null&&!node.isLeftThread) {
node = node.left;
}
}
}
}
//按照前驱方式中序遍历二叉树
public static void middlePreShow(Node node) {
//找最右边的一个节点
while(node.right != null && !node.isRightThread) {
node = node.right;
}
while(node != null) {
System.out.print(node.value + ", ");
//如果左指针是线索
if(node.isLeftThread) {
node = node.left;
} else {
//如果左指针不是线索,找到左子树开始的节点
node = node.left;
while(node.right != null && !node.isRightThread) {
node = node.right;
}
}
}
}
public static void main(String[] args) {
int[] arr = new int[] {12,32,11,9,4,5,2,34,21,20};
//创建完全二叉树
Node nod = createBinaryTree(arr,0);
//中序线索化二叉树
middleThreadBinaryTree(nod);
//中序后继遍历
middleListShow(nod);
System.out.println();
//中序前驱遍历
middlePreShow(nod);
}
}