主页免付费文档,供大家课设,学习参考,希望可以帮到小伙伴们
对于n个结点的二叉树,在二叉链存储结构中有n+1个空链域,利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继结点的指针,这些指针称为线索,加上线索的二叉树称为线索二叉树。
这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种。
算法核心
中序线索二叉树的遍历\n分两步
①获取中序遍历的首节点。
②获取中序线索化二叉树中当前节点的后继节点。只要完成这两步就可以遍历中序线索化二叉树。
//中序线索化算法
void Inthread(BiTree root)
{
if(root!=NULL)
{
Inthread(root->LChild); //通过递归线索化左子树
if(root->LChild==NULL) //当前结点的左子树为空
{
root->LChild=pre; // 第一步 置前驱线索
root->Ltag=1; //左标志域为1
}
if(pre!=NULL&&pre->RChild==NULL) //刚刚访问的结点不为空且右子树为空
{
pre->RChild=root; // 第二步 置后驱线索
pre->Rtag=1; //右标志域为1
}
pre=root; // 第三步 pre指向当前访问的结点
Inthread(root->RChild); //递归线索化右子树
}
}
中序遍历线索二叉树
获取中序遍历的首节点:从根节点开始沿着左指针不断向左下搜索,直到找到最左的节点。最左的节点指该节点左指针为空。
获取中序线索化二叉树中当前节点的后继节点:有两种情况
①当前节点存在右子树:则从该右子树根节点开始不断向左下搜索,找到找到最左的节点。该节点即当前节点的后继。
②当前节点不存在右子树:则其后继节点即为其右指针域中后继线索所指节点。
5.1存储结构
//tag为0表示指向左/右孩子,为1表示指向结点的前驱/后继
typedef struct ThreadNode{
ElemType data; //数据元素
struct ThreadNode *lchild,*rchild;// 左右孩子指针
int ltag;// 因为定义结构体时,并未给其分配内存,所以初值是无法存储的。应该声明结构体变量后,手工赋值
int rtag; //左右线索标记
}ThreadNode,*ThreadTree;
5.2函数
打印了传入的节点的数据。为了完整地遍历整个树并打印所有节点的数据
void visit(ThreadTree T)
//将二叉树转换为线索二叉树的函数
void InThread(ThreadTree &p,ThreadTree &pre)
//通过中序遍历建立中序线索二叉树的主过程算法如下:
void CreateInThread(ThreadTree &T)
//求中序线索二叉树中,中序序列下的第一个结点
ThreadNode *Firstnode(ThreadNode *p)
//求中序线索二叉树中,结点p在中序序列下的后继
ThreadNode *Nextnode(ThreadNode *p)
//利用上面的两个算法,写出不含头结点的中序线索二叉树的中序遍历算法
void Inorder(ThreadNode *T)
//创建线索二叉树,按前序输入
bool CreateThreadTree(ThreadTree &T)
//释放空间
bool DestroyThreadTree(ThreadTree T)
//中序遍历线索二叉树
void InOrder(ThreadTree T)
//主函数,控制台打印
int main()
5.3函数关系
打印了传入的节点的数据。为了完整地遍历整个树并打印所有节点的数据
void visit(ThreadTree T){
printf("%c ",T->data);
}
通过中序遍历建立中序线索二叉树的主过程算法:
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);//递归,线索化右子树
}//if(p != NULL)
}
//通过中序遍历建立中序线索二叉树的主过程:
void CreateInThread(ThreadTree &T){
//ThreadNode *Head = (ThreadNode*)malloc(sizeof(ThreadNode));
// Head->lchild=T;
//Head->ltag=1;
//ThreadTree pre=T;
ThreadTree pre=NULL;
if(T){ //非空二叉树,线索化
InThread(T,pre);//线索化二叉树
//Head->rchild=pre;
//Head->rtag=1;
pre->rchild==NULL;
//pre->rchild=T;//处理遍历的最后一个结点,将最后一个节点的右指针指向树根
pre->rtag=1;//设置最后一个节点的右标签为1,表示这是最后一个后继线索
}
}
//求中序线索二叉树中,中序序列下的第一个结点
ThreadNode *Firstnode(ThreadNode *p){
//printf("Firstnode:");
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);
}
}
//创建线索二叉树,按前序输入, #表示空节点
bool CreateThreadTree(ThreadTree &T){
ElemType ch;
scanf("%c", &ch);
if(ch == '#'){
//printf("您要创建一棵空树吗?\n");
T=NULL;
return false;
}
else{
T=(ThreadTree)malloc(sizeof(ThreadNode));
T->ltag=T->rtag=0;
if(!T){
printf("malloc failure\n");
return false;
}
T->data = ch;
CreateThreadTree(T->lchild);
CreateThreadTree(T->rchild);
return true;
}
}
//释放空间
bool DestroyThreadTree(ThreadTree T){
if(T==NULL){
printf("空节点\n");
return false;
}
if(T->ltag!=1)
DestroyThreadTree(T->lchild);
if(T->rtag!=1)
DestroyThreadTree(T->rchild);
printf("销毁%c\n",T->data);
free(T);//@@@'
T=NULL;
return true;
}
//中序遍历线索二叉树
void InOrder(ThreadTree T){
if(T){
if(T->ltag!=1)
InOrder(T->lchild);
visit(T);
if(T->rtag != 1)
InOrder(T->rchild);
}
}
//主函数
int main()