线索二叉树

  用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。但是常常我们会想要更加直观的知道节点的前驱后继。线索二叉树显得尤为的重要。

wKioL1cZ4PHAQI1dAAATb_tS_YE250.png


  线索二叉树的关键就是要定义一个全局变量来存放上一个访问过的结点。

  Node* prev;

(一)前序线索二叉树

wKioL1cZ4Rnh5EcpAAAalaSqfkY164.png

	void PrevOrderTag()
	{
		_PrevOrderTag(_root);
	}
	void _PrevOrderTag(Node* root)//前序线索二叉树
	{
		if (root == NULL)
			return;
		if (!root->_left)
		{
			root->_leftTag = THREAD;
			root->_left = prev;
		}
		if (prev && !prev->_right)
		{
			prev->_rightTag = THREAD;
			prev->_right = root;
		}
		prev = root;
		if (root->_leftTag == LINK)//只有当_leftTag为LINK时递归修改前驱后继
			_PrevOrderTag(root->_left);
		if (root->_rightTag == LINK)
			_PrevOrderTag(root->_right);
	}
	void PrevOrderTagPrint()//前序线索化打印
	{
		Node* cur = _root;
		//while (cur)
		//{
		//	while (cur->_leftTag == LINK)
		//	{
		//		cout << cur->_data << " ";
		//		cur = cur->_left;
		//	}
		//	cout << cur->_data << " ";
		//	cur = cur->_right;
		//}
	//2.
		while (cur)
		{
			cout << cur->_data << " ";
			if (cur->_leftTag == LINK)
			{
				cur = cur->_left;
			}
			else
			{
				cur = cur->_right;
			}
		}
	}

   使用二叉树的线索打印二叉树是比较方便的,不用递归就能解决问题。只要cur不为NULL就一直寻找后继打印。

(二)中序线索二叉树

wKioL1cZ4rqD83EoAAAdvvhjOEE594.png

	void MidOrderTag()
	{
		_MidOrderTag(_root);
	}
	void _MidOrderTag(Node* root)//中序线索二叉树
	{
		if (root == NULL)
		{
			return;
		}
		if (root->_leftTag == LINK)//只有当_leftTag为LINK时递归修改前驱后继
		    _MidOrderTag(root->_left);
		    
		    
		    
		if (!root->_left)
		{
			root->_leftTag = THREAD;
			root->_left = prev;
		}
		if (prev&&!prev->_right)
		{
			prev->_rightTag = THREAD;
			prev->_right = root;
		}
		prev = root;
		
		
		
		if (root->_rightTag == LINK)
		    _MidOrderTag(root->_right);
	}
	void MidOrderTagPrint()//中序线索打印
	{
		Node* cur = _root;
		while (cur)
		{
			while (cur->_leftTag == LINK)
			{
				cur = cur->_left;
			}
			cout << cur->_data << " ";
			while (cur->_rightTag == THREAD)
			{
				cur = cur->_right;
				cout << cur->_data << " ";
			}
			cur = cur->_right;//在打印右子树之前一定保证左子树已经打印过了
		}
		cout << endl;
	}

  前序的线索化打印不难懂,但是中序得知道什么时候访问右结点,在访问了左节点后才能访问右节点。

(三)后序线索二叉树

wKioL1cZ48nB07OgAAAb2FHsZJM967.png

	void RearOrderTag()
	{
		_RearOrderTag(_root);
	}
	void _RearOrderTag(Node* root)//后序线索二叉树
	{
		if (root == NULL)
		{
			return;
		}
		if (root->_leftTag == LINK)//只有当_leftTag为LINK时递归修改前驱后继
		    _RearOrderTag(root->_left);
		if (root->_rightTag == LINK)
		    _RearOrderTag(root->_right);
		    
		    
		    
		    
		if (!root->_left)
		{
			root->_leftTag = THREAD;
			root->_left = prev;
		}
		if (prev&&!prev->_right)
		{
			prev->_rightTag = THREAD;
			prev->_right = root;
		}
		prev = root;
	}

   注意,线索二叉树只有当tag的类型为LINK时才修改结点的前驱和后继

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值