二叉树结点加上线索的二叉树称为线索二叉树,对二叉树以某种方式(前序、中序、后续)遍历使其变为线索二叉树的过程称为按照该方法对二叉树进行线索化。 在一个二叉树中,当某节点的左指针为空时,令该指针指向按照某种方式遍历二叉树时得到该节点的前驱结点;当某节点的右指针为空时,令该指针指向按照某种方式遍历二叉树时得到该节点的后继结点。结点中指向前驱结点和后继结点的指针称为线索(Thread).
但问题是无法区分:左指针指向的结点是左孩子结点还是前驱结点,右指针指向的结点是右孩子结点还是后继结点。因此需要增加两个线索标志位来区分这两种情况: enum Infor{ LINK, THREAD };
#include <iostream>
using namespace std;
enum Infor{ LINK, THREAD };//设置结点的属性
template<typename T>
struct BinaryTreeNodeThd
{
BinaryTreeNodeThd(const T& data)
: _data(data)
, _pLeft(NULL)
, _pRight(NULL)
, _leftThread(LINK)
, _rightThread(LINK)
, _pParent(NULL)
{}
T _data;
BinaryTreeNodeThd<T>* _pLeft;
Infor _leftThread;
BinaryTreeNodeThd<T>* _pRight;
Infor _rightThread;
BinaryTreeNodeThd<T>* _pParent;
};
template<typename T>
class BinaryTreeThd
{
public:
BinaryTreeThd()
{}
BinaryTreeThd(T array[], size_t size)
{
size_t index = 0;
_CreateBinaryTreeThd(_pRoot, array, size, index);
}
void PreThread()//前序线索化
{
BinaryTreeNodeThd<T>* prev = NULL;
_PreThread(_pRoot, prev);
}
void PreOrder()//前序遍历线索二叉树
{
BinaryTreeNodeThd<T>* pCur = _pRoot;
while (pCur)
{
while (pCur && pCur->_leftThread == LINK)
{
cout << pCur->_data << " ";
pCur = pCur->_pLeft;
}
cout << pCur->_data << " ";
pCur = pCur->_pRight;
}
}
void InThread()//中序线索化
{
BinaryTreeNodeThd<T>* prev = NULL;
_InThread(_pRoot, prev);
}
void InOrder()//中序遍历线索二叉树
{
BinaryTreeNodeThd<T>* pCur = _pRoot;
while (pCur)
{
while (pCur && pCur->_leftThread == LINK)
{
pCur = pCur->_pLeft;
}
cout << pCur->_data << " ";
while (pCur && pCur->_rightThread == THREAD)
{
pCur = pCur->_pRight;
cout << pCur->_data << " ";
}
if (pCur)
{
pCur = pCur->_pRight;
}
}
}
void PostThread()//后序线索化
{
BinaryTreeNodeThd<T>* prev = NULL;
_PostThread(_pRoot, prev);
}
void PostOrder()//后序遍历线索二叉树
{
BinaryTreeNodeThd<T>* pCur = _pRoot;
BinaryTreeNodeThd<T>* prev = NULL;
while (pCur)
{
// 找最左边的结点
if (pCur->_pLeft != prev)
{
while (pCur->_leftThread == LINK)
pCur = pCur->_pLeft;
}
while (pCur && pCur->_rightThread == THREAD)
{
cout << pCur->_data << " ";
prev = pCur;
pCur = pCur->_pRight;
}
// 左单支的情况
if (pCur == _pRoot && pCur->_pRight == prev)
{
cout << pCur->_data << " ";
return;
}
// 右单支的情况
while (pCur && pCur->_pRight == prev)
{
cout << pCur->_data << " ";
prev = pCur;
pCur = pCur->_pParent;
}
// 当前节点如果有右子树
if (pCur && pCur->_rightThread == LINK)
{
pCur = pCur->_pRight;
}
}
}
private:
void _CreateBinaryTreeThd(BinaryTreeNodeThd<T>*& pRoot, T array[], size_t size, size_t& index)
{
if (index < size && '#' != array[index])
{
pRoot = new BinaryTreeNodeThd<T>(array[index]);
_CreateBinaryTreeThd(pRoot->_pLeft, array, size, ++index);
if (pRoot->_pLeft)
{
pRoot->_pLeft->_pParent = pRoot;
}
_CreateBinaryTreeThd(pRoot->_pRight, array, size, ++index);
if (pRoot->_pRight)
{
pRoot->_pRight->_pParent = pRoot;
}
}
}
void _PreThread(BinaryTreeNodeThd<T>*& pRoot,BinaryTreeNodeThd<T>*& prev)
{
if (pRoot)
{
//线索化当前节点的左指针域
if (NULL == pRoot->_pLeft)
{
pRoot->_pLeft = prev;
pRoot->_leftThread = THREAD;
}
//线索化当前节点的前驱节点的右指针域
if (prev && NULL == prev->_pRight)
{
prev->_pRight = pRoot;
prev->_rightThread = THREAD;
}
prev = pRoot;
if (pRoot->_leftThread == LINK)
_PreThread(pRoot->_pLeft, prev);
if (pRoot->_rightThread == LINK)
_PreThread(pRoot->_pRight, prev);
}
}
void _InThread(BinaryTreeNodeThd<T>*& pRoot, BinaryTreeNodeThd<T>*& prev)
{
if (pRoot)
{
_InThread(pRoot->_pLeft, prev);
if (NULL == pRoot->_pLeft)
{
pRoot->_pLeft = prev;
pRoot->_leftThread = THREAD;
}
if (prev && NULL == prev->_pRight)
{
prev->_pRight = pRoot;
prev->_rightThread = THREAD;
}
prev = pRoot;
if (pRoot->_rightThread == LINK)
_InThread(pRoot->_pRight, prev);
}
}
void _PostThread(BinaryTreeNodeThd<T>*& pRoot, BinaryTreeNodeThd<T>*& prev)
{
if (pRoot)
{
_PostThread(pRoot->_pLeft, prev);
_PostThread(pRoot->_pRight, prev);
if (NULL == pRoot->_pLeft)
{
pRoot->_pLeft = prev;
pRoot->_leftThread = THREAD;
}
if (prev && NULL == prev->_pRight)
{
prev->_pRight = pRoot;
prev->_rightThread = THREAD;
}
prev = pRoot;
}
}
private:
BinaryTreeNodeThd<T>* _pRoot;
};
void FunTest()
{
//char arr[] {'0','1','3','#','6','#','#','4','#','#','2','5'};
char arr[] = {'a','b','d','e','f','#','#','g','#','h','#','l','#','#','#','#','c'};
BinaryTreeThd<char> t(arr, sizeof(arr)/sizeof(arr[0]));
//t.PreThread();
//t.PreOrder();
//t.InThread();
//t.InOrder();
t.PostThread();
t.PostOrder();
}
int main()
{
FunTest();
system("pause");
return 0;
}