线索二叉树

中序线索二叉树

线索二叉树就是在原本的二叉树中将其空的指针域赋上前驱指针或者后继指针

中序遍历:左->根->右

①当指针域不为空,向左进行遍历,找到最左边的结点

②如果该结点的右孩子为空,标记前tag,并使前驱指向左孩子

③如果该结点的前驱为空,标记后tag,并使后继指向右孩子

结点结构

在原本的二叉树上再添加两个标记:Ltag,Rtag;Ltag=0表示有左孩子,Ltag=1表示有前驱;Rtag同理

遍历

因为有了前驱与后继,所以可以像数组一样进行遍历,但是需要(在中序遍历中)找到线索二叉树的第一个结点与他的next,即后继指针,从而进行遍历

其他处理

因为中序遍历会遍历到最后一个结点,所以最后一个结点的Rtag=1;最后一个结点的Rchild=NULL

#include<iostream>
using namespace std;
typedef struct TreeNode
{
	char data;
	struct TreeNode* Lchild;
	struct TreeNode* Rchild;
	int Ltag;//0表示有孩子,1表示有前驱或者后继
	int Rtag;
}TreeNode;
void creatTree(TreeNode** T, char* x, int* index)
{
	char ch;
	ch = x[*index];
	*index +=1;
	if (ch == '#')
	{
		*T = NULL;
	}
	else
	{
		*T = new TreeNode;
		(*T)->data = ch;
		(*T)->Ltag = 0;//因为有孩子,所以设置为0
		(*T)->Rtag = 0;
		creatTree(&(*T)->Lchild, x, index);
		creatTree(&(*T)->Rchild, x, index);
	}
}
void visit(TreeNode* T)
{
	cout << T->data << " ";
}
void threadTree(TreeNode* T, TreeNode** pre)
{
	if (T != NULL)
	{
		threadTree(T->Lchild, pre);
		if (T->Lchild == NULL)//没有左孩子,可以有前驱
		{
			T->Ltag = 1;//标记为有前驱
			T->Lchild = *pre;//T根节点的左孩子保存为*pre前驱
		}
		if (*pre != NULL&&(*pre)->Rchild==NULL)//自己不为NULL,且右孩子为NULL,可以做后继
		{
			(*pre)->Rtag = 1;
			(*pre)->Rchild = T;
		}
		*pre = T;
		threadTree(T->Rchild, pre);
	}
}
TreeNode* getFirst(TreeNode* T)
{
	while (T->Ltag == 0)//第一个结点的前驱为NULL,Ltag为1
	{
		T = T->Lchild;
	}
	return T;
}
TreeNode* getNext(TreeNode* T)
{
	if (T->Rtag == 1)//即当前结点有后继,直接返回后继
	{
		return T->Rchild;
	}
	else//当前结点有孩子,就找这棵树的第一个结点
	{
		return getFirst(T->Rchild);
	}
}
int main()
{
	char arry[16] = { 'A','B','D','#','#','E','#','#','C','F','#','#','G','#','#' };
	TreeNode* T = new TreeNode;
	TreeNode* pre = NULL;
	int index = 0;
	creatTree(&T, arry, &index);
	threadTree(T, &pre);//通过创建线索树,T根结点移动到最后一个结点上
	pre->Rtag = 1;//最后一个结点有后继,其后继的右孩子为NULL
	pre->Rchild = NULL;
	for (TreeNode* node = getFirst(T); node != NULL; node = getNext(node))
	{
		cout << node->data << " ";
	}
	cout << endl;

}

前序遍历

#include<iostream>
using namespace std;
typedef struct TreeNode
{
	char Tdata;
	struct TreeNode* Lchild;
	struct TreeNode* Rchild;
	bool Ltag;
	bool Rtag;
};
void creatTree(TreeNode** T, char* x, int* index)
{
	char ch;
	ch = x[*index];
	*index += 1;
	if (ch == '#')
		*T = NULL;
	else
	{
		*T = new TreeNode;
		(*T)->Tdata = ch;
		(*T)->Ltag = 0;
		(*T)->Rtag = 0;
		creatTree(&(*T)->Lchild, x, index);
		creatTree(&(*T)->Rchild, x, index);
	}
}
void visit(TreeNode* T)
{
	cout << T->Tdata << " ";
}
void preThreadTree(TreeNode* T, TreeNode** pre)
{
	if (T)
	{
		if (T->Lchild == NULL)
		{
			T->Ltag = 1;
			T->Lchild = *pre;
		}
		if (*pre != NULL && (*pre)->Rchild==NULL)
		{
			(*pre)->Rtag = 1;
			(*pre)->Rchild = T;
		}
		*pre = T;
		if(T->Ltag==0)
			preThreadTree(T->Lchild,pre);
		preThreadTree(T->Rchild,pre);
	}
}
TreeNode* getNext(TreeNode* T)
{
	if (T->Rtag == 1)//如果没有右孩子
	{
		return T->Rchild;//直接返回后继
	}
	else//有右孩子
	{
		if (T->Ltag == 0)//又看成一个根结点,有左孩子,直接返回其左孩子当做前驱
			return T->Lchild;
		else
			return T->Rchild;
	}
}
/*
TreeNode* getNext(TreeNode* T)
{
	if (T->Ltag == 0)
		return T->Lchild;
	else
		return T->Rchild;
}*/
int main()
{
	char arry[16] = { 'A','B','D','#','#','E','#','#','C','F','#','#','G','#','#' };
	TreeNode* T;
	TreeNode* pre = NULL;
	int index = 0;
	creatTree(&T, arry, &index);
	preThreadTree(T, &pre);
	(*pre).Rtag = 1;
	(*pre).Rchild = NULL;
	cout << "前序遍历:";
	for (TreeNode* node = T; node != NULL; node = getNext(node))
	{
		visit(node);
	}
	cout << endl;
}

后序遍历

#include<iostream>
using namespace std;
typedef struct TreeNode
{
	char data;
	struct TreeNode* Lchild;
	struct TreeNode* Rchild;
	struct TreeNode* Parent;
	int Ltag;
	int Rtag;
}TreeNode;
void createTree(TreeNode** T, char* x, int* index, TreeNode* parent)
{
	char ch;
	ch = x[*index];
	*index += 1;
	if (ch == '#')
	{
		*T = NULL;
	}
	else
	{
		*T = new TreeNode;
		(*T)->data = ch;
		(*T)->Ltag = 0;
		(*T)->Rtag = 0;
		(*T)->Parent = parent;
		createTree(&(*T)->Lchild, x, index, *T);
		createTree(&(*T)->Rchild, x, index, *T);
	}
}
void visit(TreeNode* T)
{
	cout << T->data << " ";
}
void postThreadTree(TreeNode* T, TreeNode** pre)
{
	if (T)
	{
		postThreadTree(T->Lchild, pre);
		postThreadTree(T->Rchild, pre);
		if (T->Lchild == NULL)
		{
			T->Ltag = 1;
			T->Lchild = *pre;
		}
		if (*pre != NULL && (*pre)->Rchild == NULL)
		{
			(*pre)->Rtag = 1;
			(*pre)->Rchild = T;
		}
		*pre = T;
	}

}
TreeNode* getFirst(TreeNode* T)
{
	while (T->Ltag == 0)
	{
		T = T->Lchild;
	}
	if (T->Rtag == 0)
		return getFirst(T->Rchild);
	return T;
}
TreeNode* getNext(TreeNode* T)
{
	if (T->Rtag == 1)
		return T->Rchild;
	else
	{
		//判断是否是根结点
		if (T->Parent == NULL)
			return NULL;
		else if (T == T->Parent->Rchild)//如果是右孩子(说明左孩子已经遍历了)
		{
			return T->Parent;
		}
		else//如果是左孩子
		{
			if (T->Parent->Rtag == 0)//如果当前结点的Parent有右孩子,就获得右孩子那一分支的第一个结点
			{
				return getFirst(T->Parent->Rchild);
			}
			else
			{
				return T->Parent;
			}
		}
	}
}
int main()
{
	char arry[16] = { 'A','B','D','#','#','E','#','#','C','F','#','#','G','#','#' };
	TreeNode* T;
	TreeNode* pre = NULL;
	int index = 0;
	createTree(&T, arry, &index, NULL);
	postThreadTree(T, &pre);
	cout << "后序遍历:";
	for (TreeNode* node = getFirst(T); node != NULL; node = getNext(node))
	{
		visit(node);
	}
	cout << endl;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值