利用二叉链表中的空指针域:
- 如果某个节点的左孩子为空,则将空的左孩子的指针域改为指向其前驱;
- 如果某个节点的右孩子为空,则将空的右孩子的指针域改为指向其后继;
- 这种改变指向的指针称为“线索”,加上了线索的二叉树称为线索二叉树,对二叉树按某种遍历次序使其变为线索二叉树的过程叫做线索化。
为区分lchild和rchild指针到底是指向孩子的指针还是指向前驱后继的指针,对二叉链表的每个结点增设两个标识域ltag和rtag,并约定:
- ltag = 0 lchild指向该节点的左孩子
- ltag = 1 lchild指向该节点的前驱
- rtag = 0 rchild指向该节点的右孩子
- rtag = 1 rchild指向该节点的后继
增加头结点
增加一个头结点
- ltag = 0,lchild指向根节点
- rtag = 1,rchild指向遍历序列中最后一个结点
- 遍历序列中第一个节点的lc域和最后一个结点的rc域都指向头结点,如图所示。
- 找到了前驱,就可以找到头结点,通过头结点又可以访问到其他的节点;
- 而当我们找到了最后的一个节点,有可以顺着指针找到头结点再找到其他的节点。
线索二叉树的数据结构
typedef enum{
link, //表示指向左右孩子的指针
thread, //表示指向前驱后继的线索
}TreePointTag;
typedef struct TbinaryTree{
char data;
struct TbinaryTree *lchild;
struct TbinaryTree *rchild;
TreePointTag ltag;
TreePointTag rtag;
}TbinaryTree;
代码:
//线索二叉树的数据结构
typedef enum{link,thread}PointTag;
typedef struct BiThrNode{
char data;
struct BiThrNode *lchild;
struct BiThrNode *rchild;
PointTag ltag;
PointTag rtag;
}BiThrNode,*BiThrTree;
//线索二叉树的创建
BiThrNode* CreateBiThrTree()
{
BiThrNode* T;
char c;
scanf("%c",&c);
if(' ' == c)
T = NULL;
else
{
T = (BiThrNode *)malloc(sizeof(BiThrNode));
T->data;
T->data = c;
T->ltag = link;
T->rtag = link;
T->lchild = CreateBiThrTree();
T->rchild = CreateBiThrTree();
}
return T;
}
//全局变量,始终指向刚刚访问过的节点
BiThrTree pre;
//中序遍历线索化
InThreading(BiThrTree T)
{
if(T)
{
InThreading(T->lchild); //递归左孩子线索化
//节点处理,中序和之前遍历树的操作不同,但是结构相同
if( !T->lchild) //如果该节点没有左孩子
{
T->ltag = thread; //设置为线索
T->lchild = pre; //指向前驱节点,也就是上一个访问的节点
}
if( !pre->rchild ) //右子树为空的情况才可以设置线索
{
pre->rtag = thread; //设置为线索
pre->rchild = T; //指向后继节点,也就是当前访问的节点
}
pre = T; //处理完当前节点之后,T就成为前一个节点,然后接着往下
InThreading(T->rchild); //递归右孩子线索化
}
}
//增加头结点并对pre进程初始化
InOrderThreading(BiThrTree head,BiThrTree T)
{
head = (BiThrTree)malloc(sizeof(BiThrTree));
head->ltag = link;
head->rtag = thread;
head->rchild = head; //指向本身
if( !T ) //如果为空树
head->lchild = head;
else //如果不是空树
{
head->lchild = T;
pre = head; //对pre进行初始化
InThreading(T); //中序遍历线索化
//收尾处理
pre->rchild = head;
pre->rtag = thread;
head->rchild = pre;
}
}
//中序遍历二叉树,非递规
void InOrderTraverse(BiThrTree T)
{
BiThrTree p;
p = T->lchild;
while( p != T )
{
while( p->ltag == link )
p = p->lchild;
printf("%c",p->data);
while(p->rtag == thread && p->rchild != T)
{
P = P->rchild;
printf("%c",p->data);
}
p = p->rchild; //指回头结点
}
}
参考链接:https://www.bilibili.com/video/av35340088