全知识整理目录
数据结构整理的目录包括了许多的数据结构相关知识。
目录
概述
什么是线索二叉树?
为了区分二叉树的左孩子指针,和右孩子指针是否为空,为结点增加了2个域,这两个域分别是Ltag和Rtag。这样的二叉树,就是线索二叉树。
需要了解的概念
如果结点有左孩子:那么Lchild指向他的左孩子,否则指向遍历序列中他的前驱结点。
如果结点有右孩子:那么Rchild依然指向他的左孩子,否则指向遍历序列的后继节点。
Ltag=0:表示Lchild指向结点的左孩子。
Ltag=1:表示Lchild指向结点的遍历前驱。
Rtag=0:表示Rchild指向结点的左孩子。
Rtag=1:表示Rchild指向结点的遍历后继。
ps:0左,1前后。
线索:指向前驱和后继结点的指针。
线索化:将空指针改为线索的过程。
实例
如下图二叉树实例,先后进行先序,中序,后序。
其实无论是什么样的序列化,只需要记得下面这三句话:
- 如果结点有左孩子:那么Lchild指向他的左孩子,否则指向遍历序列中他的前驱结点。
- 如果结点有右孩子:那么Rchild依然指向他的左孩子,否则指向遍历序列的后继节点。
- 前驱或者后驱没有,就为NULL。
先序
中序
后序
上述二叉搜索树的过程实现,只需要记住开始的那几句话,就基本能够实现了。
代码实现
如何使用代码实现,先,中,后序的二叉序列树。
下面以中序线索化为例:
首先遍历到,左孩子指针域为空的时候,这时候就要访问他的前驱结点,所以需要定义一个全局的pre来记录刚刚访问过的结点,将pre赋给他的左孩子域,将Ltag设置为1。
当遍历到右孩子指针域为空的时候,要填写的结点应该是,该结点的后续结点,但是当前无法确认后继节点,因此当前节点右孩子的指针域,只能遍历到下一个结点的时候在填写,并且当前结点就是pre结点的后继结点,所以需要回填pre,如果pre的右孩子结点为空,那么当前的结点赋值给pre右节点,同时pre结点的Rtag设置为1。
#define pre
void mid_thiread(BiThree root)
{
if(root!=NULL)
{
mid_thiread(root->Lchild); //递归线索化root的左孩子
if(root->Lchild == NULL) //左孩子为空,则指向他的前驱pre
{
root->Lchild = pre;
root->Ltag = 1;
}
else{
root->Ltag = 0; //左孩子不为空,Ltag=0;
}
if(pre != NULL && pre->Rchild == NULL) //右孩子为空,指向他的后继
{
pre->Rchild =root;
pre->Rtag =1;
}
pre = root;
mid_thiread(root->Rchild); //递归线索化root右孩子
}
}
中序线索二叉树,寻找首结点
首先访问的是,往最左下端走,找到的第一个没用左孩子的结点。
BiTree InFirst(BiTree bt){
//寻找最左下角,第一个没有左孩子的结点
BiTree p =bt;
if(p == NULL)
return NULL;
while(p->Ltag == 0)
p = p->Lchild;
return p;
}
寻找结点的后继
寻找,后继结点,就是寻找到后续第一个没有左孩子的结点。
BiTree in_next(BiTree p){
BiTree next,q;
if(p->Rtag == 1)
{
next = P->Rchild; //使用线索化
}
else
{
for(q = p->Rchild; q->Ltag == 0; q = q->Lchild);
next = q;
}
return(next);
}
参考博客