线索二叉树

线索二叉树:

n个结点的二叉树有n+1个空指针,利用这些空指针来存放指向前驱或后继的指针

遍历线索化

例如:中序线索化,在中序遍历访问结点的时候进行线索化

设置一个全局变量pre指向当前访问结点的前一个

具体代码如下:

void visit(ThreadNode *q){
	if(q->lchild==NULL){
		q->lchild=pre;
		q->ltag=1;
	}
	if(pre!=NULL&&pre->rchild==NULL){
		pre->rchild=q;
		pre->rtag=1;
	}
	pre=q;
}

遍历到最后一个结点的时候pre=q,需要再处理一下pre的后继

if(pre->rchild==NULL)
			pre->rtag=1;

完整代码:

ThreadNode *pre=NULL;
//中序线索化二叉树
void CreatInThread(ThreadTree T){
	pre=NULL;
	if(T!=NULL){
		InThread(T);
		if(pre->rchild==NULL)
			pre->rtag=1;//处理遍历的最后一个结点 
	}
} 
//线索二叉树结点
typedef struct ThreadTree{
	ElemType data;
	struct ThreadNode *lchild,*rchild;
	int ltag,rtag;//左右标志线索 
}ThreadNode,*ThreadTree;

//中序遍历二叉树,一边遍历一边线索化
void InThread(ThreadTree T){
	if(T!=NULL){
		InThread(T->lchild);
		visit(T);//在访问时线索化 
		InThread(T->rchild);
	}
} 

void visit(ThreadNode *q){
	if(q->lchild==NULL){
		q->lchild=pre;
		q->ltag=1;
	}
	if(pre!=NULL&&pre->rchild==NULL){
		pre->rchild=q;
		pre->rtag=1;
	}
	pre=q;
}

先序线索化思路一样,但可能会出现“原地打转”的现象

需要通过ltag辨别是左孩子还是前驱

void PreThread(ThreadTree T){
	if(T!=NULL){
		visit(T);//在访问时线索化 
        if(T->ltag==0)
            PreThread(T->lchild);
		preThread(T->rchild);
	}
} 

后序线索化思路相同

查找线索二叉树的前驱和后继结点

中序线索二叉树:

后继:

1.该结点已经被线索化,则后继结点就是next

2.未被线索化,则需要找到该结点的右分支的最左下角的结点(左根右)

void *FirstNode(ThreadTree *p){
	while(p->ltag==0)//存在左孩子则继续往下寻找
		p=p->lchild;
	return p; 
}
ThreadNode *NextNode(ThreadNode *p){
	if(p->rtag==0) return FirstNode(p->rchild);//右分支最左下的结点
	else return p->rchild; 
}

利用线索二叉树实现中序遍历(利用线索实现中序遍历的非递归算法)

void InOrder(ThreadNode *T){
	while(ThreadNode *p=FirstNode(T);p!=NULL;p=NextNode(p))
		visit(p);
}
中序线索二叉树的前驱结点:

1.已线索化的前驱

2.未被线索化,左分支的最右下的结点

ThreadNode *LastNode(ThreadNode *p){
	while(rtag==0) p=p->rchild;
	return p;
}
ThreadNode *PreNode(ThreadNode *p){
	if(p->ltag==0) return LastNode(p->lchild);
	else return p->lchild;
} 

利用中序前驱逆向中序遍历

void RevInoder(ThreadNode *T){
	for(ThreadNode *p=LastNode(T);p!=NULL;p=PreNode(p))
		visit(p);
}

先序线索二叉树

先序:根 左 右

后继:1.rtag==1

2.rtag=0,存在右分支,需要考虑是否存在左孩子

2.1左孩子存在,即后继是左孩子

2.2左孩子不存在,则后继是右孩子

ThreadNode *NextNode(ThreadNode *p){
	if(p->rtag==0){
		if(p->lchild!=NULL) return p->lchild;
		else return p->rchild;
	}
	else return p->rchild;
} 
前驱

1.ltag=1

2.ltag=0 无法找到

解决:增加指向父结点的指针,改造成三叉链表

能找到p的父结点,则存在以下情况:

1.p是左孩子 p->pre=父结点

2.p是右孩子

2.1左兄弟为空 p->pre=父结点

2.2左兄弟非空,p->pre=左兄弟先序遍历最后一个被访问的结点(不一定是最右的)

3.p是根节点,无前驱

后序线索二叉树思路相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值