数据结构-线索链表

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

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

首先是辅助宏的定义:

#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)

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值