数据结构-线索链表

版权声明:转载请注明出处。 https://blog.csdn.net/baidu_38304645/article/details/82980692

遍历二叉树时结点访问的先后顺序信息只有子啊遍历的动态过程中得到。若经常遍历或者要求取遍历时结点的前驱、后继信息则应修改二叉链表的结构以保存该遍历顺序链表,加上线索的二叉树称为线索二叉树。分先序、中序、后序线索二叉树。

这里介绍的是中序线索二叉树.

首先是辅助宏的定义:

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define UNDERFLOW -2
#define NULL 0
#define TREE_SIZE 1
#define TREEINCREMENT 1
typedef int Status;
typedef char TElemType;
typedef enum {LINK,THREAD} PointerTag; //指针标记类型
/*LINK 0 代表指向孩子的指针
THREAD 1 代表为指向前驱后继的线索*/

线索链表的存储结构定义:

//线索链表的存储结构定义
typedef struct BiThrNode{
   TElemType data;
   struct BiThrNode *lchild,*rchild;//左右指针
   PointerTag LTag,RTag;//指针性质LINK或者THREAD
}BiThrNode,*BiThrTree;

输出e 输出二叉树 调用先序遍历函数 用函数传递给其参数visit即可.

Status PrintTElem(TElemType e){
	//输出e 输出二叉树 调用先序遍历函数 用函数传递给其参数visit即可
   printf("%c",e);
   return OK;
}

先序创造线索链表各节点 注意输入时空指针不要丢 输入空格是空树,停止 否则创造根节点 递归创造左子树, 递归创造右子树.

Status CreatBiTree(BiThrTree &T){
	/*先序创造线索链表各节点 注意输入时空指针不要丢
	输入空格是空树,停止 否则创造根节点 递归创造左子树
	递归创造右子树*/
   TElemType e;
   scanf("%c",&e);
   if(e==' ')
	   T=NULL;
   else{
       T=(BiThrTree)malloc(sizeof(BiThrNode));
       if(!T)//存储分配失败
           exit(OVERFLOW);
	   T->data=e;
	   T->lchild=NULL;
	   T->rchild=NULL;
	   CreatBiTree(T->lchild);
	   CreatBiTree(T->rchild);
   }
   return OK;
}

遍历以p为根的树并添加前驱和后继线索信息 pre指向遍历后第一个结点的前驱 函数返回时pre指向最后一个访问的结点 

递归求解 空时无操作 否则先递归的向左子树添加线索信息 后处理与p相关的线索信息 再递归的向右子树添加线索信息 注意处理左右子树时pre的取值..

void InTreading(BiThrTree p,BiThrTree &pre){
	/*遍历以p为根的树并添加前驱和后继线索信息 pre指向遍历后第一个结点的前驱
	函数返回时pre指向最后一个访问的结点
	递归求解 空时无操作 否则先递归的向左子树添加线索信息 后处理与p相关的线索信息
	再递归的向右子树添加线索信息 注意处理左右子树时pre的取值*/
   if(p){
       InTreading(p->lchild,pre);
       if(!p->lchild){
	       p->LTag=THREAD;
	       p->lchild=pre;
	   }
	   else
		   p->LTag=LINK;
       if(!pre->rchild) { 
	       pre->RTag=THREAD;
	       pre->rchild=p;
	   }
       else
	      pre->RTag=LINK;
	   pre=p; //修改pre
	   InTreading(p->rchild,pre);
   }
}

T为原二叉树 T指向树的根结点 将T中序线索化为Thrt,开辟头结点并赋初值 遍历原二叉树 根据有无孩子修改标记并适时添加线索信息 最后结点单独处理.

Status InOrderTheading(BiThrTree &Thrt,BiThrTree T){
	//T为原二叉树 T指向树的根结点 将T中序线索化为Thrt
	//开辟头结点并赋初值 遍历原二叉树 根据有无孩子修改标记并适时添加线索信息 最后结点单独处理
   Thrt=(BiThrTree)malloc(sizeof(BiThrNode));
   if(!Thrt)
       exit(OVERFLOW);
   BiThrNode *pre;
   Thrt->lchild=Thrt;//假设T为空
   Thrt->LTag=LINK;
   Thrt->RTag=THREAD;
   Thrt->rchild=Thrt;
   if(T){
	   Thrt->lchild=T;
       pre=Thrt;
       InTreading(T,pre);
       pre->RTag=THREAD;//处理最后一个结点
       pre->rchild=Thrt;
	   Thrt->rchild=pre;
   }
   return OK;
}

中序遍历线性链表.  令p指向原树根 设法让p指向第一个应该访问的结点 只要左孩子不空就令他指向左孩子 即 第一个左标记不为LINK的结点 访问p 只要p->THREAD 就让p=p->rchild 并访问p 否则令p指向右子树的根  重复上面操作 直到p指向头结点 遍历完毕.

复杂度也为O(n),但是没有递归,不需要栈。

Status InOrderTraverse_Thr(BiThrTree T,Status (*visit)(TElemType)){
	/*中序遍历线性链表
	令p指向原树根 设法让p指向第一个应该访问的结点 只要左孩子不空就令他指向左孩子 即
	第一个左标记不为LINK的结点 访问p 只要p->THREAD 就让p=p->rchild 并访问p 否则令p指向右子树的根
	重复上面操作 直到p指向头结点 遍历完毕*/
    BiThrNode *p=T->lchild;//p访问根结点
    while(p!=T){//未遍历结束
	    while(p->LTag==LINK) //p指向第一个待访问的结点
	        p=p->lchild;
	    if(!visit(p->data))
	        return ERROR;
	    while(p->RTag==THREAD&&p->rchild!=T){
			//只要是线索就前进
			p=p->rchild;
		    if(!visit(p->data))
		        return ERROR;
		}
		p=p->rchild;//当前结点右子树非线索 p指向右子树根
	}
    return OK;
}//T(n)=O(n)

猜你喜欢

转载自blog.csdn.net/baidu_38304645/article/details/82980692