线索二叉树的建立与部分应用

在n个结点的二叉链表中,有(n+1)个空指针域,利用这些空指针域来存放当前结点的直接前驱和后继的线索,可以加快查找速度。


普通二叉树只能找到结点的左右孩子信息,而结点的直接前驱和直接后继只能在遍历中获得,若将遍历后对应的前驱和后继预存起来,从第一个结点开始就可以顺藤摸瓜而遍历整棵树,树实际变成了线性序列。线索化二叉树实际上就是把二叉树转化成了线性排列,具有唯一前趋和唯一后继。
 

线索二叉树结构声明:

typedef struct node{
	struct node* left;
	struct node* right;
	int ltag = 0;		//tag标志位标志该指针是指向左/右孩子还是线索 
	int rtag = 0;		//若tag=1则为线索 
	char val;
}TreeNode,*Tree; 

TreeNode *pre = NULL;

 

中序建立线索二叉树:

算法思想:

一个pre指针一直指向t遍历的前一个结点,每次遍历到一个结点,如果可以做线索的话,刚好做的是t 的左线索和 pre 的右线索。

这样的话当t遍历完时候pre 的右线索还没有处理,此时 pre 指向遍历完之后的最后一个结点,我们给pre 的右线索置1收尾。
 

 

//中序遍历构建线索二叉树 
void InThread(Tree& t,TreeNode* &pre)
{
	if(t == NULL) return;
	InThread(t->left,pre);
	
	if(t->left == NULL)
	{
		t->left = pre;
		ltag = 1;
	}
	
	if(pre && pre->right = NULL)
	{
		pre->right = t;
		pre->rtag = 1;
	}
	pre = t;
	InThread(t->right,pre);
 } 
 
void creatThread(Tree &t)
{
	TreeNode *p = NULL;
	if(t != NULL){
		InThread(t,pre);
		t->rtag = 1; 		//最后一个右标志位置1 
	}
}

寻找中序序列下的后继结点:

算法思想:

如果该结点p的 p->rtag = 1,则直接返回 p->right(该结点的右孩子)为该结点的后继结点;

如果该结点p的 p->rtag = 0,则该结点具有右子树,p的后继结点的应该为它右子树中序遍历中的第一个结点也就是最左边的结点;

//中序序列的后继结点
TreeNode* successor(TreeNode* p)
{
	if(p->rtag == 1) return p->right;
	p = p->right;                       //访问该结点的右子树寻找其中序遍历的第一个结点
	while(p->ltag == 0) p = p->left;    //找到第一个没有右孩子的结点 
	return p;
}

中序遍历中序线索二叉树:

算法思想:

先找到该树中序遍历的第一个结点(最左下方的结点),然后从第一个结点开始依次找每个结点的中序后继,最后输出即可。

//中序遍历中序线索二叉树
void InOrder(Tree &t)
{
	TreeNode *p = t;
	while(p->ltag == 0) 
	p = p->left;		//找到中序遍历的第一个结点(左下角的结点)
	for(p; p!=NULL; p=successor(p))
		cout << p->val << " ";
 } 

 中序序列下的前驱结点:

算法思想:

如果结点的 ltag == 1 ,那么直接返回 p->left;

如果该结点有左孩子,那么该结点的前驱结点应该是其左子树的最右下角的结点;

//中序序列下的前驱结点
TreeNode* prior(TreeNode* p) 
{
	if(p->right == 1)	return p->right;
	p = p->left;                            //访问左子树
	while(p->rtag == 0)	p = p->right;		//找到第一个没有右孩子的结点 
	return p;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值