线索二叉树简介
线索二叉树是以一定规则将二叉树中的节点排列成一个线性序列,得到二叉树中节点的先序,中序和后序序列.这实质上是对一个非线性结构进行线性化操作,是每一个节点(除去第一个和最后一个)都有且仅有一个直接前驱和后继.
二叉树节点创建
用java创建二叉树节点结构,创建一个Node类,他的对象就是一个节点.
class Node{
//值域
private int value;
//左右子树
public Node leftNode = null;
public Node rightNode = null;
//左右标识
public int lTage ;
public int rTage ;
//双亲节点,后序线索二叉树需要用到
public Node parent = null;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
中序线索二叉树
个人觉得中序线索二叉树是最容易理解的一种线索二叉树了.下面说一下如何构造以及遍历线索二叉树
构造中序线索二叉树
构造中序线索二叉树具体分为五部
1.如果当前节点p飞空,根据中序的规定,应该先对其左字数递归线索化.
2.如果p的左孩子为空,需要给p加上左线索,也就是他的前驱,并将其LTag(本文中的算法将LTag和RTag命名为lTage和rTage)设置为1,让p的做孩子指向pre(p的前驱,也就是上一个访问的节点),否则就把LTage设置为0.
3.如果pre的右孩子为空,需要给pre加上右线索(后继),并将RTage设置为1,让pre的右孩子指向p,否则RTage就为0.
4.迭代pre,pre=p
5.右字数递归线索化,重复第2至4步.
public void InThreading(Node p) {
if(p!=null) {
InThreading(p.leftNode);
if(p.leftNode != null) {
p.lTage = 0;
}else {
p.lTage = 1;
p.leftNode = this.pre;
}
if(pre.rightNode!=null) {
p.rTage = 0;
}else {
pre.rTage = 1;
pre.rightNode = p;
}
pre = p;
InThreading(p.rightNode);
}
}
遍历中序线索二叉树
在遍历中序线索二叉树之前,应该先了解,怎么在中序线索二叉树中找到节点的前驱和后继
查找当前节点p的前驱:
当p->LTage为1的时候,p的左孩子直接指向的就是他的前驱.
当p->LTage为0的时候,p的左孩子指向的是p的左子树的根,p和他的前驱pre之间是没有任何链来连接的.但通过中序遍历的特性可以知道,当前节点p的前驱应该是中序遍历其左子树的最后一个节点.
例如下图 ,根节点A的具有左子树,根据中序遍历的,该二叉树的中序遍历序列为DBEAC,A的前驱应该是E。而节点C不具有左子树,访问节点C之前,访问的是结点A,
所以pre=A,C的前驱是A
查找当前节点p的后继:
当p->RTage为1的时候,p的右孩子直接指向的就是他的后继.
当p->RTage为0的时候,p的后继是他右子树访问的第一个节点。如上图,A的后继就为C
遍历中序线索二叉树代码如下
public void selectThread(Node t) {
//t是一个头结点,具体为什么使用头结点,在详细代码中有介绍,这里只需要知道t的左子树指向的是二叉树的根
Node p = t.leftNode;
//当p不等于t的时候说明二叉树还没有遍历完成,博主在定义线索二叉树的时候,都在根节点之前加
//了一个头结点,线索二叉树遍历的第一个节点的前驱为头结点,而最后一个节点的后继也是头结点。
while(p!=t) {
//这个循环用于取得当前节点左子树根据中序遍历所得出的第一个节点,也就是左子树的最左下节点。
while(p.lTage != 1) {
p = p.leftNode;
}
//取得以当前节点p为根的树根据中序遍历得出的第一个节点。
System.out.println(p.getValue());
//判断p是否有后继,如果有后继则沿着后继一直访问下去&#