二叉树的线索化(一)

本篇文章主要整理二叉树的先序和中序线索化,以及对线索树的两种遍历。

线索化的引入:

对于有n个节点的二叉树中,就会有n+1个空指针,导致空间的浪费。

推导:对于任何一棵二叉树,叶子节点也就是度为0的节点数为n0,度为2的节点数为

n2,则有n0 = n2+1。(总结点数为n)

n0+n1+n2  = n

n2+1 = n0.

两等式联立:2*n0+n1 = n+1.

所以我们引入了线索化二叉树,即就是对空指针域的充分利用。如果该结点有左右子树,

左右指针域指向其左右孩子,如果没有左子树(或者右子树),左指针域(或者

右指针域)指向其前驱(或者后继)。这里就需要有左右的标注,lTag和rTag。如果是

0,说明指向其孩子,如果是1,说明指向其前驱(或者后继)。

下边画图举例说明:


首先还是得先创建一棵二叉树,像前边的方法那样,递归完成。

先序线索化二叉树:


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


中序线索化二叉树:

对于中序线索化,就是类似先序线索化了,只是根节点的访问时间不一样罢了。

这里就不给出图解了。文末将会给出全部代码~~~

中序遍历中序线索树:


下边给出实现代码:

#pragma once
#include<iostream>
using namespace std;
#include<assert.h>

enum Type
{
	LINK,//指向孩子
	THREAD//指向前驱或者后继
};
template<typename T>
struct BinaryTreeTNode
{
	T _data;
	BinaryTreeTNode* _lchild;
	BinaryTreeTNode* _rchild;
	Type _lTag;
	Type _rTag;
	BinaryTreeTNode(const T& x = T())
		:_data(x)
		,_lchild(NULL)
		,_rchild(NULL)
		,_lTag(LINK)
		,_rTag(LINK)
	{}
};

template<typename T>
class BinaryTreeThreading
{
	typedef BinaryTreeTNode<T> Node;
public:
	BinaryTreeThreading(T* a, size_t size, const T& invalid)
		:_root(NULL)
		,prev(NULL)
	{
		size_t index = 0;
		_root = _Create(a, size, index, invalid);
	}
	void PreOrderThreading()
	{
		_PreOrderThreading(_root);
	}
	void InOrderThreading()
	{
		_InOrderThreading(_root);
	}
	void InOrder()//中序遍历线索二叉树
	{
		Node* cur = _root;
		while (cur)
		{
			while (cur->_lTag == LINK)
			{
				cur = cur->_lchild;
			}
			cout << cur->_data << " ";
			while (cur->_rTag == THREAD && cur->_rchild != NULL)
			{
				cur = cur->_rchild;
				cout << cur->_data << " ";
			}
			cur = cur->_rchild;
		}
		cout << endl;
	}
	void PreOrder()//先序遍历
	{
		Node* cur = _root;
		while (cur)
		{
			while (cur->_lTag == LINK)
			{
				cout << cur->_data << " ";
				cur = cur->_lchild;
			}
			cout << cur->_data << " ";
			
			cur = cur->_rchild;
		}
		cout << endl;
	}

protected:
	
	Node* _Create(T* a,size_t size,size_t& index,const T& invalid)
	{
		assert(a != NULL);
		Node* root = NULL;
		if (a[index] != invalid && index < size)
		{
			root = new Node(a[index]);
			root->_lchild = _Create(a, size, ++index, invalid);
			root->_rchild = _Create(a, size, ++index, invalid);
		}
		return root;
	}
	
	void _PreOrderThreading(Node* root)
	{

		if (root)
		{
			if (!root->_lchild)
			{
				root->_lTag = THREAD;
				root->_lchild = prev;        //前继线索
			}
			if (prev && !prev->_rchild)
			{
				prev->_rTag = THREAD;
				prev->_rchild = root;        //后继线索
			}
			prev = root;
			if (LINK == root->_lTag)
				_PreOrderThreading(root->_lchild);
			if (LINK == root->_rTag)
				_PreOrderThreading(root->_rchild);
		}
	}
	
	
	void _InOrderThreading(Node* root)
	{
		if (root)
		{
			_InOrderThreading(root->_lchild);
			if (root->_lchild == NULL)
			{
				root->_lTag = THREAD;
				root->_lchild = prev;
			}
			if (prev && prev->_rchild == NULL)
			{
				prev->_rTag = THREAD;
				prev->_rchild = root;
			}
			prev = root;
			_InOrderThreading(root->_rchild);
		}
	}

private:
	Node* _root;
	Node* prev;
};


测试代码:

#include"BinaryTreeThreading.h"
void test()
{
	int array1[10] = { 1, 2, 3, '#', '#', 4, '#' , '#', 5, 6 };
	BinaryTreeThreading<int> b1(array1,10,'#');
	b1.InOrderThreading();
	b1.InOrder();
	
	int array2[15] = { 1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8 };
	BinaryTreeThreading<int> b2(array2, 15, '#');
	b2.PreOrderThreading();
	b2.PreOrder();

}
int main()
{
	test();
	system("pause");
	return 0;
}


先序线索和中序线索先到这里,后序线索之后补充~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值