17、线索二叉树的生成和遍历

一、相关概念及思想介绍

1、n个结点有n-1个前驱和n-1个后继;一共有2n个链域,其中:n+1个空链域,n-1个指针域;因此, 可以用空链域来存放结点的前驱和后继。线索二叉树就是利用n+1个空链域来存放结点的前驱和后继结点的信息。

2、线索:有效利用二叉链表中空的存储空间,指定原有的孩子指针为空的域来存放指向前驱和后继的信息,这样的指针被称为“线索”。加线索的过程称为线索化,由此得到的二叉树称作线索二叉树。如下图中:

        

若结点有左子树,则左链域lchild指示其左孩子(ltag=0);否则,令左链域指示其前驱(ltag=1);

若结点有右子树,则右链域rchild指示其右孩子(rtag=0);否则,令右链域指示其后继(rtag=1);

增设一个头结点,令其lchild指向二叉树的根结点,ltag=0、rtag=1;并将该结点作为遍历访问的第一个结点的前驱和最后一个结点的后继;最后用头指针指示该头结点。其rchild域的指针指向中序遍历时访问的最后一个结点;反之,令二叉树中序序列中的第一个结点的lchild域指针和最后一个结点rchild域的指针均指向头结点,这好比为二叉树建立了一个双向线索链表,既可以从第一个结点起顺后继进行遍历,也可以从最后一个结点起顺前驱进行遍历。见3的例子中。

3、例子:如下图a示的二叉树,其中序线索二叉树为图b所示:

二、二叉树的存储结构

struct node

{ ElemenType data;             //数据域

 int ltag;                    //左标志域

 int rtag;                    //右标志域

 struct node *lchild;         //左指针域 

 struct node *rchild;         //右指针域

}BTree;

三、算法的C语言描述

如下为中序遍历建立中序遍历线索化链表的算法:

如下为线索二叉树遍历算法:

四、算法的C语言实现

#include "stdio.h"

#include "stdlib.h"

#define OK 1

typedef char TElemType;

typedef int Status;

typedef enum PointerTag {Link,Thread}; //link==0:pointer,Thread==1:thread

typedef struct BiThrNode

{

TElemType data;

struct BiThrNode *lchild,*rchild;

PointerTag LTag,RTag;

}BiThrNode,*BiThrTree;

BiThrTree pre; // 全局变量,始终指向刚刚访问过的结点

void InThreading(BiThrTree p)

{

if(p)

  {

   InThreading(p->lchild);//左子树线索化

   if(!p->lchild){p->LTag=Thread;p->lchild=pre;}//前驱线索

   if(!pre->rchild){pre->RTag=Thread;pre->rchild=p;}//后续线索

   pre=p; //保持pre指向p的前驱

   InThreading(p->rchild);//右子树线索化

  }//if

}//InThreading

Status InOrderThreading(BiThrTree &Thrt,BiThrTree T)

{

//中序遍历二叉树,并将其中序线索化,Thrt指向头结点

//BiThrTree Thrt;

if(!(Thrt=(BiThrTree)malloc(sizeof(BiThrNode)))) exit(-1);

Thrt->LTag=Link; //建立头结点

Thrt->RTag=Thread; //右指针回指

Thrt->rchild=Thrt; 

if(!T) Thrt->rchild=Thrt; //若二叉树为空,则左指针回指

else {

     Thrt->lchild=T;

        pre=Thrt;

     InThreading(T);  //中序遍历进行中序线索化

     pre->rchild=Thrt;//最后一个结点线索化

        pre->RTag=Thread;

        Thrt->rchild=pre;

     }

return OK;

}//InOrderThreading

Status InOrderTraverse_Thr(BiThrTree T)

{

//T指向头结点,头结点的左链lchild指向根结点,非递归算法

BiThrTree p; 

p=T->lchild;

while(p!=T) //空树或遍历结束时,T==p

       {

   while(p->LTag==Link) p=p->lchild;

   printf("%c\n",p->data); //访问其左子树为空的结点

   while(p->RTag==Thread&&p->rchild!=T)

          {

              p=p->rchild;

              printf("%c\n",p->data); //访问后续结点

          }//while

   p=p->rchild;

       }//while

return OK;

}//InOrderT_Thr

Status CreateBitree(BiThrTree &T)

{//按先序次序输入二叉树

char ch,enter;

scanf("%c%c",&ch,&enter);

if(ch==' ') T=NULL;

else{

    if(!(T=(BiThrTree)malloc(sizeof(BiThrNode)))) exit(1);

       T->data=ch;

       CreateBitree(T->lchild);

       CreateBitree(T->rchild);

    }//else

return OK;

}//CreateBitree

int main()

{

BiThrTree T,Thrt;

CreateBitree(T);//创建

InOrderThreading(Thrt,T);//线索化

InOrderTraverse_Thr(Thrt);//遍历访问

return OK;

}

注意点:在输入字符创立二叉树时,要注意叶子结点的输入形式,即叶子结点的左右空指针也要输入,在我们这里输入空格。

发布了278 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/104534048