线索化二叉树学习(C语言)
一、线索二叉树的基本概念
传统的二叉链表存储仅能体现一种父子关系,不能直接得到结点在遍历中的前驱或后继。我们知道,在含n个结点的二叉树中,有n+1个空指针。利用这些空指针来存放其前驱或后继的指针,这样就可以使得我们在遍历二叉树时可以像遍历单链表那样方便。引入线索二叉树正是为了加快查找结点前驱和后继的速度。(有三种线索化二叉树,分别是先序线索化二叉树、中序线索化二叉树以及后序线索化二叉树)
二、中序线索化二叉树创建、找前驱、找后继以及遍历
#include<stdio.h>
#include<stdlib.h>
//二叉树结构
typedef struct ThreadNode{
int data;
struct ThreadNode *lchild,*rchild;//左右孩子指针
int ltag,rtag;//左右孩子线索标志
}ThreadNode,*ThreadTree;
//中序遍历线索化二叉树的过程函数
void InThread(ThreadTree &p,ThreadTree &pre){
if(p!=NULL){
InThread(p->lchild,pre);
if(p->lchild==NULL){
p->lchild=pre;
p->ltag=1;
}
if(pre!=NULL&&pre->rchild==NULL){
pre->rchild=p;
pre->rtag=1;
}
pre=p;
InThread(p->rchild,pre);
}
}
//中序遍历建立中序线索二叉树
void CreateInThread(ThreadTree T){
ThreadTree pre=NULL;
if(T!=NULL){
InThread(T,pre);
pre->rchild==NULL;
pre->rtag=1;
}
}
//访问结点函数
void visit(ThreadTree T){
printf("%d->",T->data);//打印结点数据
}
//找到以p为根的子树第一个被中序遍历的结点
ThreadNode *FirstNode(ThreadNode *p){
//循环找到最左下结点(不一定是叶结点)
while(p->ltag==0){
p=p->lchild;
}
return p;
}
//在中序线索二叉树中找到结点p的后继结点
ThreadNode *NextNode(ThreadNode *p){
//右子树中最左下结点
if(p->rtag==0){
return FirstNode(p->rchild);
}else{
return p->rchild;//rtag==1直接返回后继线索
}
}
//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)
void InOrder(ThreadNode *T){
for(ThreadNode *p=FirstNode(T);p!=NULL;p=NextNode(p)){
visit(p);
}
}
//找到以P为根的子树中,最后一个被中序遍历的结点
ThreadNode *LastNode(ThreadNode *p){
//循环找到最右下结点(不一定是叶结点)
while(p->rtag==0){
p=p->rchild;
}
return p;
}
//在中序线索二叉树中找到结点p的前驱结点
ThreadNode *PreNode(ThreadNode *p){
//左子树中最右下结点
if(p->ltag==0){
return LastNode(p->lchild);
}else{
return p->lchild;//ltag==1直接返回前驱线索
}
}
//对中序线索二叉树进行逆向中序遍历
void ReInOrder(ThreadNode *T){
for(ThreadNode *p=LastNode(T);p!=NULL;p=PreNode(p))
visit(p);
}
int main(){
//测试结点数据
ThreadTree t1=(ThreadTree)malloc(sizeof(ThreadNode));
ThreadTree t2=(ThreadTree)malloc(sizeof(ThreadNode));
ThreadTree t3=(ThreadTree)malloc(sizeof(ThreadNode));
ThreadTree t4=(ThreadTree)malloc(sizeof(ThreadNode));
ThreadTree t5=(ThreadTree)malloc(sizeof(ThreadNode));
t1->data=1;t1->lchild=t2;t1->rchild=t3;t1->ltag=t1->rtag=0;
t2->data=2;t2->lchild=t4;t2->rchild=t5;t2->ltag=t2->rtag=0;
t3->data=3;t3->lchild=NULL;t3->rchild=NULL;t3->ltag=t3->rtag=0;
t4->data=4;t4->lchild=NULL;t4->rchild=NULL;t4->ltag=t4->rtag=0;
t5->data=5;t5->lchild=NULL;t5->rchild=NULL;t5->ltag=t5->rtag=0;
//线索化二叉树
CreateInThread(t1);
//中序(顺序)打印
InOrder(t1);
printf("\n");
//中序(逆序)打印
ReInOrder(t1);
}
三、前中后序线索化二叉树的找前驱、找后继比较
中序线索二叉树 | 先序线索二叉树 | 后序二叉树 | |
---|---|---|---|
找前驱 | √ | × | √ |
找后继 | √ | √ | × |