一,线索二叉树的引入:
1,含有n个节点的二叉树有n-1条分支线,那么空指针域的个数=2n-(n-1) = n+1个,这n+1个空指针域浪费了内存资源。
2,中序方式遍历二叉树某节点的前驱节点或者后继节点时,必须要按中序方式遍历二叉树才能够知道结果,每次需要结果时都需要进行一次遍历,浪费了时间性能。
综合以上两方面的分析,可以通过充分利用二叉树中的空指针域,存放节点在某种遍历方式下的前驱和后继节点的指针。我们把这种指向前驱和后继的指针成为线索,加上线索的二叉树就称为线索二叉树。
二,线索二叉树的代码实现:
1,不同于普通二叉树的结构,线索二叉树的每个节点还需要标明当前的左右指针是线索指针还是子节点指针,这就需要修改节点的数据结构。修改后的数据结构如下:
class TreeNode{
int val;
TreeNode left;
TreeNode right;
int leftType;//类型为1,指向前驱,类型为0,指向左节点
int rightType;//类型为1,指向后继,类型为0,指向有节点
public TreeNode(int val) {
this.val = val;
}
}
2,中序线索化的实现代码如下(和中序遍历的唯一区别就是由打印改成线索化实现):
public class ThreadedBinaryTree {
TreeNode pre;//前驱节点
//中序遍历线索化
public void threadedNodes(TreeNode root){
if(root==null) return;
threadedNodes(root.left);//线索化左子树
//若当前节点的左子树为空,则修改为指向其前驱
if(root.left==null){
root.left = pre;
root.leftType = 1;
}
//判断当前节点的前驱节点不为空且其右子树为空,则改其右指针指向当前节点
if(pre!=null&&pre.right==null){
pre.right = root;
pre.rightType = 1;
}
//更新前驱节点
pre = root;
threadedNodes(root.right);//线索化右子树
}
//线索化遍历
public void threadedList(TreeNode root){
while (root!=null){
//找到第一个被线索化的节点,开始遍历
while (root.leftType==0){
root = root.left;
}
System.out.print(root.val+"\t");
while (root.rightType==1){
root = root.right;
System.out.print(root.val+"\t");
}
root = root.right;
}
System.out.println();
}
@Test
public void test(){//测试中序线索化二叉树的功能
TreeNode root = new TreeNode(1);
TreeNode root2 = new TreeNode(3);
TreeNode root3 = new TreeNode(6);
TreeNode root4 = new TreeNode(8);
TreeNode root5 = new TreeNode(10);
TreeNode root6 = new TreeNode(14);
root.left = root2;
root.right = root3;
root2.left = root4;
root2.right = root5;
root3.left = root6;
threadedNodes(root);
threadedList(root);
}