二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息.
- 二叉树的结构
enum PointerTag
{
THREAD, //线索化指针的标记
LINK //一般指针的标记
};
template <class T>
struct BinaryTreeNode_Thd
{
//构造函数
BinaryTreeNode_Thd()
: _date(0)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
BinaryTreeNode_Thd(const T& d)
: _date(d)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
T _date; //数据
BinaryTreeNode_Thd<T>* _left; //左孩子
BinaryTreeNode_Thd<T>* _right;//右孩子
PointerTag _leftTag; //左孩子线索标志
PointerTag _rightTag; //右孩子线索标志
};
2.中序线索化
void InOrderThreading()
{
Node* prev = NULL;
_InOrderThreading(_root, prev);
}
//中序线索化遍历
void InOrderThd()
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag == LINK)
{
cur = cur->_left;
}
cout << cur->_date << " ";
while (cur->_leftTag == THREAD)
{
cur = cur->_right;
cout << cur->_date << " ";
}
cur = cur->_right;
}
cout << endl;
}
//中序线索化
void _InOrderThreading(Node* cur,Node*& prev)
{
if (cur == NULL)
return;
_InOrderThreading(cur->_left, prev); //左子树
//线索化左
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
//访问到下一个节点后,线索化上一个节点右
if (prev && prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
_InOrderThreading(cur->_right, prev); //右子树
}
3.前序线索化
//前序线索化
void PrevOrderThreading()
{
Node* prev = NULL;
_PrevOrderThreading(_root, prev);
}
//前序线索化遍历
void PrevOrderThd()
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag != THREAD)
{
cout << cur->_date << " ";
cur = cur->_left;
}
cout << cur->_date << " ";
cur = cur->_right;
}
cout << endl;
}
void _PrevOrderThreading(Node* cur, Node*& prev)
{
if (cur == NULL)
return;
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
if (prev && prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
if (cur->_leftTag == LINK)
{
_PrevOrderThreading(cur->_left, prev);
}
if (cur->_rightTag == LINK)
{
_PrevOrderThreading(cur->_right, prev);
}
}
4.后序线索化
//后序线索化
void PostOrderThreading()
{
Node* prev = NULL;
_PostOrderThreading(_root, prev);
}
//后序线索化
void _PostOrderThreading(Node* cur, Node*& prev)
{
if (cur == NULL)
return;
_PostOrderThreading(cur->_left, prev);
_PostOrderThreading(cur->_right, prev);
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
if (prev && prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
}
5.完整代码
#include <iostream>
#include <cstdlib>
using namespace std;
enum PointerTag
{
THREAD, //线索化指针的标记
LINK //一般指针的标记
};
template <class T>
struct BinaryTreeNode_Thd
{
//构造函数
BinaryTreeNode_Thd()
: _date(0)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
BinaryTreeNode_Thd(const T& d)
: _date(d)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
T _date; //数据
BinaryTreeNode_Thd<T>* _left; //左孩子
BinaryTreeNode_Thd<T>* _right;//右孩子
PointerTag _leftTag; //左孩子线索标志
PointerTag _rightTag; //右孩子线索标志
};
template <class T>
class BinaryTreeThread
{
typedef BinaryTreeNode_Thd<T> Node;
public:
BinaryTreeThread()
:_root(NULL)
{}
BinaryTreeThread(T* a, size_t n, const T& invalid)
{
size_t index = 0;
_root = _CreateTree(a, n, index, invalid);
}
//中序线索化
void InOrderThreading()
{
Node* prev = NULL;
_InOrderThreading(_root, prev);
}
//中序线索化遍历
void InOrderThd()
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag == LINK)
{
cur = cur->_left;
}
cout << cur->_date << " ";
while (cur->_leftTag == THREAD)
{
cur = cur->_right;
cout << cur->_date << " ";
}
cur = cur->_right;
}
cout << endl;
}
//前序线索化
void PrevOrderThreading()
{
Node* prev = NULL;
_PrevOrderThreading(_root, prev);
}
//前序线索化遍历
void PrevOrderThd()
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag != THREAD)
{
cout << cur->_date << " ";
cur = cur->_left;
}
cout << cur->_date << " ";
cur = cur->_right;
}
cout << endl;
}
//后序线索化
void PostOrderThreading()
{
Node* prev = NULL;
_PostOrderThreading(_root, prev);
}
protected:
//后序线索化
void _PostOrderThreading(Node* cur, Node*& prev)
{
if (cur == NULL)
return;
_PostOrderThreading(cur->_left, prev);
_PostOrderThreading(cur->_right, prev);
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
if (prev && prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
}
//前序线索化
void _PrevOrderThreading(Node* cur, Node*& prev)
{
if (cur == NULL)
return;
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
if (prev && prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
if (cur->_leftTag == LINK)
{
_PrevOrderThreading(cur->_left, prev);
}
if (cur->_rightTag == LINK)
{
_PrevOrderThreading(cur->_right, prev);
}
}
//中序线索化
void _InOrderThreading(Node* cur,Node*& prev)
{
if (cur == NULL)
return;
_InOrderThreading(cur->_left, prev); //左子树
//线索化左
if (cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
//访问到下一个节点后,线索化上一个节点右
if (prev && prev->_right == NULL)
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
_InOrderThreading(cur->_right, prev); //右子树
}
Node* _CreateTree(const T* a, size_t size, size_t& index, const T& invalid)
{
Node* NewNode = NULL;
if (index < size && a[index] != invalid)
{
NewNode = new Node(a[index]);
NewNode->_left = _CreateTree(a, size, ++index, invalid);
NewNode->_right = _CreateTree(a, size, ++index, invalid);
}
return NewNode;
}
protected:
Node* _root;
};
void Test()
{
int a1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
int a2[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
BinaryTreeThread<int> a(a1, 10, '#');
//a.InOrderThreading();
//a.InOrderThd();
//a.PrevOrderThreading();
//a.PrevOrderThd();
a.PostOrderThreading();
}
int main()
{
Test();
return 0;
}