文章目录
1.设计算法构造一棵先序线索二叉树
在构建先序线索二叉树的过程中,最值得说明的就是中间的核心操作,T代表当前的指针,pre代表它的前一个指针。
先序序列:ABCDE
BiTNode *pre = NULL; // 定义一个全局变量,保存当前结点的前驱结点
void preOrderThreading(BiTree T) //先序线索化二叉树
{
//对根节点处理
if(T==NULL) return; //该结点是空树,则啥也不干
if(T->lchild==NULL)
{
T->ltag=1;
T->lchild=pre;
printf("%d %c %d\n",T->ltag,T->data,T->rtag);
}
if(pre!=NULL&&pre->rchild==NULL) //为什么pre要不等于空,因为后面要用到pre->rchild.NULL是没有右孩子的,如调用会报错
{
pre->rtag=1;
pre->rchild=T;
printf("%d %c %d\n",pre->ltag,pre->data,pre->rtag);
}
//在先序线索化的过程中,我们需要遍历整棵二叉树。递归调用 PreThreading 函数时,必须确保不在递归过程中错误地访问线索指针,这就是为什么需要检查 ltag 和 rtag 的原因。
pre=T; //进入T的子树前,将pre指针后移
if(T->ltag==0) preOrderThreading(T->lchild);
if(T->rtag==0) preOrderThreading(T->rchild);
}
void creatthreadtree(BiTree T)
{
pre=NULL;
if(T!=NULL)
{
preOrderThreading(T);
if(pre->rchild==NULL)
{
T->rtag=1;
}
}
}
2.先序线索二叉树的先序遍历算法
先序线索二叉树就不需要常规二叉树那种递归遍历的方法,而是线性的遍历。
大体上来说,先序线索化二叉树的前驱结点(第一个结点)肯定是根节点,从它出现,开始进行先序遍历,无非有下面的几种情况。
1.存在左孩子,左孩子就是它的下一个结点
2.不存在左孩子,右孩子就是它的下一个结点
3.既不存在左孩子,又不存在右孩子,那么就访问它的线索,即右孩子指向的后继结点
其中,情况2和情况3操作的过程是一样的,所以,写代码的过程中,归为一种。
综上所述,写代码时就是1+23
->>简单来说
如果存在左孩子则左孩子肯定是后继,没有左孩子就遍历右孩子,假如左右孩子都没有,直接访问后继即可,后继就是右孩子。
为什么不一直访问后继?很明显线索化只是打通了部分原先本没有左孩子或者右孩子的路径,给它们前驱或者后继
//前序线索二叉树的遍历
void preOrderTravers(BiTree T)
{
BiTNode *preNode=T; //找到根节点,定义操作根节点的指针