线索化二叉树&&线索化后的二叉树遍历

能看到线索化二叉树这块的对于一些概念性的问题肯定就有了一定的了解,这里就不多说了,下面直接上正餐

因为线索话的话,当左子树为为空的时候我们需要让其指向其前驱元素,当右子数为空的时候我们需要让其指向其后继的元素,这样就把整个二叉树线索化起来了,因为我们就需要标记一下左右子树是否被线索花,在这里我们用枚举来作为标记

enum//用来标记是否线索化,LINK表示有左右子树没有被线索化,THREAD表示被线索化
{
	LINK,
	THREAD,
};

因为我是用C++写的,所以这里先给出创建二叉树的代码

#include<iostream>
using namespace std;
#pragma once
enum//用来标记是否线索化,LINK表示有左右子树没有被线索化,THREAD表示被线索化
{
	LINK,
	THREAD,
};
template<class T>
struct BinTreeNode
{
	BinTreeNode<T> *lchild;
	BinTreeNode<T> *rchild;
	int leftflag;//左边的标志
	int rightflag;//右边的标志
	T _data;
	BinTreeNode(T& data)
		:_data(data)
		, lchild(NULL)
		, rchild(NULL)
		, leftflag(LINK)
		, rightflag(LINK)
	{}
};
template<class T>
class BinNode
{
public:
	typedef BinTreeNode<T> * _PNode;
	typedef BinTreeNode<T> Node;
private:
	_PNode _pRoot;
public:
	BinNode()
		:_pRoot(NULL)
	{}
	BinNode(T *array, size_t size, T invalue)//创建一颗二叉树
		:_pRoot(NULL)
	{
		size_t index = 0;
		_CreatNode(_pRoot, array, size, index, invalue);
	}
private:
	void _CreatNode(_PNode &pRoot, T* array, size_t size, size_t& index, T invalue)//创建一颗二叉树
		{
			if (index >= size||invalue == array[index])
				return;
			pRoot= new Node(array[index]);
			_CreatNode(pRoot->lchild, array, size, ++index, invalue);
			_CreatNode(pRoot->rchild, array, size, ++index, invalue);
		}
};
int  main()
{
	char *arr = "ABD##E##CF###";
	BinNode<char> s(arr, strlen(arr), '#');
	system("pause");
	return 0;
}


然后在在上面的基础上添加线索花的功能!

一.前序遍历的顺序线索化二叉树&&前序顺序遍历线索化后的二叉树

首先给出我二叉树的形象图


①前序遍历的顺序线索化二叉树代码如下(递归)

大致思路就是:首先线索花当前结点的左子树和右子树(即根节点),然后标记当前结点,然后判断是否被线索花(即是否有左右子树)然后递归遍历其左子树和右子数,结合代码和图理解

void _PreThreadTree(_PNode pRoot,_PNode &pre)//前序线索化二叉树
	{
		if (NULL == pRoot)
		{
			return;
		}
		if (pRoot->lchild == NULL)//左子树和右子树都确定不需要的时候再进行
		{
			pRoot->lchild = pre;
			pRoot->leftflag = THREAD;
		}
		if (pre != NULL&&pre->rchild == NULL)//没有右子树
		{
			pre->rchild = pRoot;
			pre->rightflag = THREAD;//线索标记
		}
		pre = pRoot;//pre记录当前的结点
		if (pRoot->leftflag == LINK)//如果没有线索花进去,避免不必要的开销
		 _PreThreadTree(pRoot->lchild,pre);
		if (pRoot->rightflag==LINK)
			_PreThreadTree(pRoot->rchild,pre);
	}
②前序顺序遍历线索花后的二叉树代码如下:

这个很简单就根据线索化后的一直往下找就可以了!

void _PreOrder(_PNode pRoot)//前序遍历线索花二叉树
	{
		while(pRoot->leftflag==LINK)
		{
			cout << pRoot->_data << " ";
			pRoot = pRoot->lchild;
		}
		cout << pRoot->_data << " ";
		while (pRoot->rightflag==THREAD)
		{
			pRoot = pRoot->rchild;
			cout << pRoot->_data << " ";
		}
	}
测试结果:

二.中序遍历的顺序线索花二叉树&&中序顺序遍历线索化后的二叉树
首先给出代码的二叉树的形象图

①中序遍历的顺序线索化二叉树代码如下

这个思路和前序的很类似就是只不是先递归到左子树,然后线索化左子树,然后递归到右子树

void _InThreadTree(_PNode pRoot, _PNode &pre)//中序线索化二叉树
	{
		if (pRoot == NULL)
		{
			return;
		}
		if (pRoot->leftflag==LINK)
		_InThreadTree(pRoot->lchild,pre);//一直遍历处理左子树
		if (pRoot->lchild == NULL)//如果左子树为空,线索化左子树
		{
			pRoot->lchild = pre;
			pRoot->leftflag = THREAD;
		}
		if (pre != NULL&&pre->rchild == NULL)
		{
			pre->rchild = pRoot;
			pre->rightflag = THREAD;
		}
		pre = pRoot;
		if (pRoot->rightflag==LINK)
		_InThreadTree(pRoot->rchild,pre);
	}
②中序遍历中序线索化后的二叉树

void _InOrder(_PNode pRoot)//线索化中序遍历
	{
		while (pRoot)
		{
			while (pRoot->leftflag == LINK)//先遍历左子树,如果被线索化证明左子树遍历完了
			{
				pRoot = pRoot->lchild;
			}
			cout << pRoot->_data << " ";//打印当前根节点
			while ((pRoot->leftflag == THREAD))//开始遍历右子树
			{
				pRoot = pRoot->rchild;
				cout << pRoot->_data << " ";
			}
			pRoot = pRoot->rchild;//左子树彻底处理完了处理右子树
		}
	}
测试结果:

三.后序遍历的顺序线索化二叉树

首先给出二叉树的形象图


后序遍历线索花的代码如下:

void _PostThreadTree(_PNode pRoot, _PNode &pre)//后续序线索化二叉树
	{
		if (pRoot)
		{
			_PostThreadTree(pRoot->lchild, pre);
			_PostThreadTree(pRoot->rchild, pre);
			if (pRoot->lchild == NULL)
			{
				pRoot->lchild = pre;
				pRoot->leftflag = THREAD;
			}
			if (pre&&pre->rchild == NULL)
			{
				pre->rchild = pRoot;
				pre->rightflag = THREAD;
			}
			pre = pRoot;
		}
	}
思路和前中的思路也很相似这里就不多说了,自己对照代码理解。

对于后序线索化的后序遍历因为比较复杂这里先不说了!可以自己去了解。

下面给出全部的代码

#include<iostream>
using namespace std;
#pragma once
enum//用来标记是否线索化,LINK表示有左右子树没有被线索化,THREAD表示被线索化
{
	LINK,
	THREAD,
};
template<class T>
struct BinTreeNode
{
	BinTreeNode<T> *lchild;
	BinTreeNode<T> *rchild;
	int leftflag;//左边的标志
	int rightflag;//右边的标志
	T _data;
	BinTreeNode(T& data)
		:_data(data)
		, lchild(NULL)
		, rchild(NULL)
		, leftflag(LINK)
		, rightflag(LINK)
	{}
};
template<class T>
class BinNode
{
public:
	typedef BinTreeNode<T> * _PNode;
	typedef BinTreeNode<T> Node;
private:
	_PNode _pRoot;
public:
	BinNode()
		:_pRoot(NULL)
	{}
	BinNode(T *array, size_t size,T invalue)//创建一颗二叉树
		:_pRoot(NULL)
	{
		size_t index = 0;
		_CreatNode(_pRoot, array, size, index, invalue);
	}
	void PreThreadTree()//前序线索花二叉树
	{
		_PNode pre = NULL;//记录前一个结点的位置
		_PreThreadTree(_pRoot,pre);
	}
	void InThreadTree()//中序线索花二叉树
	{
		_PNode pre = NULL;//记录前一个结点的位置
		_InThreadTree(_pRoot, pre);
	}
	void PostThreadTree()//后序线索化二叉树
	{
		_PNode pre = NULL;
		_PostThreadTree(_pRoot, pre);
	}
	void PreOrder()//前序遍历
	{
		_PreOrder(_pRoot);
	}
	void InOrder()//中序遍历
	{
		_InOrder(_pRoot);
	}
private:
	void _CreatNode(_PNode &pRoot, T* array, size_t size, size_t& index, T invalue)//创建一颗二叉树
	{
		if (index >= size||invalue == array[index])
			return;
		pRoot= new Node(array[index]);
		_CreatNode(pRoot->lchild, array, size, ++index, invalue);
		_CreatNode(pRoot->rchild, array, size, ++index, invalue);
	}
	//前序遍历的顺序:A  B  D  E C F
	void _PreThreadTree(_PNode pRoot,_PNode &pre)//前序线索化二叉树
	{
		if (NULL == pRoot)
		{
			return;
		}
		if (pRoot->lchild == NULL)//左子树和右子树都确定不需要的时候再进行
		{
			pRoot->lchild = pre;
			pRoot->leftflag = THREAD;
		}
		if (pre != NULL&&pre->rchild == NULL)//没有右子树
		{
			pre->rchild = pRoot;
			pre->rightflag = THREAD;//线索标记
		}
		pre = pRoot;//pre记录当前的结点
		if (pRoot->leftflag == LINK)//如果没有线索花进去,避免不必要的开销
		 _PreThreadTree(pRoot->lchild,pre);
		if (pRoot->rightflag==LINK)
			_PreThreadTree(pRoot->rchild,pre);
	}
	//中序遍历的顺序:C B E A F C
	void _InThreadTree(_PNode pRoot, _PNode &pre)//中序线索化二叉树
	{
		if (pRoot == NULL)
		{
			return;
		}
		if (pRoot->leftflag==LINK)
		_InThreadTree(pRoot->lchild,pre);//一直遍历处理左子树
		if (pRoot->lchild == NULL)//如果左子树为空,线索化左子树
		{
			pRoot->lchild = pre;
			pRoot->leftflag = THREAD;
		}
		if (pre != NULL&&pre->rchild == NULL)
		{
			pre->rchild = pRoot;
			pre->rightflag = THREAD;
		}
		pre = pRoot;
		if (pRoot->rightflag==LINK)
		_InThreadTree(pRoot->rchild,pre);
	}
	//后续遍历的顺序:D E B F C A
	void _PostThreadTree(_PNode pRoot, _PNode &pre)//后续序线索化二叉树
	{
		if (pRoot)
		{
			_PostThreadTree(pRoot->lchild, pre);
			_PostThreadTree(pRoot->rchild, pre);
			if (pRoot->lchild == NULL)
			{
				pRoot->lchild = pre;
				pRoot->leftflag = THREAD;
			}
			if (pre&&pre->rchild == NULL)
			{
				pre->rchild = pRoot;
				pre->rightflag = THREAD;
			}
			pre = pRoot;
		}
	}
	void _PreOrder(_PNode pRoot)//前序遍历线索花二叉树
	{
		while(pRoot->leftflag==LINK)
		{
			cout << pRoot->_data << " ";
			pRoot = pRoot->lchild;
		}
		cout << pRoot->_data << " ";
		while (pRoot->rightflag==THREAD)
		{
			pRoot = pRoot->rchild;
			cout << pRoot->_data << " ";
		}
	}
	void _InOrder(_PNode pRoot)//线索化中序遍历
	{
		while (pRoot)
		{
			while (pRoot->leftflag == LINK)//先遍历左子树,如果被线索化证明左子树遍历完了
			{
				pRoot = pRoot->lchild;
			}
			cout << pRoot->_data << " ";//打印当前根节点
			while ((pRoot->leftflag == THREAD))//开始遍历右子树
			{
				pRoot = pRoot->rchild;
				cout << pRoot->_data << " ";
			}
			pRoot = pRoot->rchild;//左子树彻底处理完了处理右子树
		}
	}
};
int  main()
{
	char *arr= "ABD##E##CF###";
	BinNode<char> s(arr, strlen(arr), '#');
	/*s.PreThreadTree();*/
	/*s.InThreadTree();*/
	s.PostThreadTree();
	/*s.PreOrder();*/
	/*s.InOrder();*/
	system("pause");
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值