1. 用线索化的原因
二叉链表作为存储结构是,为了方便、快速找到结点的直接前驱和直接后继。这种动态的访问方法是充分利用二叉链表中的空链域,将遍历过程中结点的前驱、后继信息保存下来。
2. 线索二叉树结点的结构
有 n 个结点的二叉链表有 2n 个链域;空链域:n+1个;非空链域:n-1 个(两点之间连的线);
了解线索的概念
按照不同的遍历次序分为:先序线索二叉树、中序线索二叉树、后序线索二叉树
3. 算法思想
- 中序线索化采用中序递归遍历算法框架
- 加线索操作就是访问结点操作
- 加线索操作需要利用刚访问的结点与当前结点的关系,因此设置一个指针 pre,始终记录刚访问过的结点
- 如果当前遍历结点 root 的左子域为空,则左子域指向 pre;
- 如果前驱 pre 的右子域为空,则让右子域指向当前遍历结点 root ;
- 为下次做准备,当前访问节点 root 作为下一个访问结点的前驱 pre;
4. 建立中序线索二叉树
核心算法
5. 完整代码
#include <stdio.h>
#include <stdlib.h>
typedef struct BiNode
{
char data;
int Ltag;
int Rtag;
struct BiNode * LChild;
struct BiNode * RChild;
}BiNode,*BiTree;
BiTree pre; //全局定义前驱指针
//创建二叉树,按先序遍历输入
void CreateBiTree(BiTree *T)
{
char ch;
scanf("%c",&ch);
if(ch=='#')
*T=NULL;
else{
*T=(BiTree) malloc (sizeof(BiNode));
(*T)->data=ch;
CreateBiTree(&(*T)->LChild);
CreateBiTree(&(*T)->RChild);
}
}
//中序线索化
void Inthread (BiTree root)
{
if (root !=NULL )
{
Inthread(root->LChild);//线索化左子树
printf(" %c ",root->data);
if (root->LChild==NULL) //找前驱
{
root->Ltag=1;
root->LChild=pre;
}
if (pre !=NULL && pre->RChild == NULL) //找后继
{
pre->RChild=root;
pre->Rtag=1;
}
pre=root; //让当前结点作为下一次的前驱
Inthread(root->RChild);//线索化右子树
}
}
int main()
{
BiTree T;
printf("请按照先序遍历的方式输入(为空是输入#): ");
CreateBiTree(&T);
printf("中序线索化: ");
Inthread(T);
printf("\n");
return 0;
}