二叉树是一种非线性结构,遍历二叉树几乎都是通过递归和借助栈完成的。
二叉树作为存储结构时,取到一个节点,只 能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
于是,为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。
这就是二叉树的线索化。
中序线索化:
前序线索化:
后序线索化:
后序线索化可以,但是用二叉链表没法进行遍历。
代码如下:
#pragma once
#include<iostream>
using namespace std;
enum PointerTag
{
THREAD,
LINK
};
template <class T>
struct BinaryTreeThdNode
{
T _data;//数据
BinaryTreeThdNode<T>* _leftchild;//左孩子
BinaryTreeThdNode<T>* _rightchild;//右孩子
PointerTag _leftTag;//左孩子线索标记
PointerTag _rightTag;//右孩子线索标记
BinaryTreeThdNode(const T& x)//构造函数
:_data(x)
, _leftchild(NULL)
, _rightchild(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
};
template <class T>
class BinaryTreeThd
{
typedef BinaryTreeThdNode<T> Node;
public:
BinaryTreeThd(T* a,size_t n,const T& invalid = T())//构造函数
{
size_t index = 0;
_root = _CreateTree(a, n, invalid, index);
}
void InOrderThreading()//中序线索化
{
Node* prev = NULL;
_InOrderThreading(_root, prev);
}
void InOrderThd()//中序线索化遍历
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag == LINK)
{
cur = cur->_leftchild;
}
cout << cur->_data << " ";
while (cur->_rightTag == THREAD)
{
cur = cur->_rightchild;
cout << cur->_data << " ";
}
cur = cur->_rightchild;
}
cout << endl;
}
void PrevOrderThreading()//前序线索化
{
Node* prev = NULL;
_PrevOrderThreading(_root, prev);
}
void PrevOrderThd()//前序遍历
{
Node* cur = _root;
while (cur)
{
while (cur->_leftTag == LINK)
{
cout << cur->_data << " ";
cur = cur->_leftchild;
}
cout << cur->_data << " ";
cur = cur->_rightchild;
}
cout << endl;
}
void PostOrderThreading()//后序线索化
{
Node* prev = NULL;
_PostOrderThreading(_root, prev);
}
protected:
void _PostOrderThreading(Node* cur, Node*& prev)//后序线索化的调用函数
{
if (cur == NULL)
return;
_PostOrderThreading(cur->_leftchild, prev);
_PostOrderThreading(cur->_rightchild, prev);
if (cur->_leftchild == NULL)//线索化左
{
cur->_leftTag = THREAD;
cur->_leftchild = prev;
}
if (prev && prev->_rightchild == NULL)//线索化右
{
prev->_rightchild = cur;
prev->_rightTag = THREAD;
}
prev = cur;
}
void _PrevOrderThreading(Node* cur, Node*& prev)//前序线索化调用函数
{
if (cur == NULL)
return;
if (cur->_leftchild == NULL)//线索化左
{
cur->_leftchild = prev;
cur->_leftTag = THREAD;
}
if (prev && prev->_rightchild == NULL)//线索化右
{
prev->_rightchild = cur;
prev->_rightTag = THREAD;
}
prev = cur;
if (cur->_leftTag == LINK)
_PrevOrderThreading(cur->_leftchild, prev);
if (cur->_rightTag == LINK)
_PrevOrderThreading(cur->_rightchild, prev);
}
void _InOrderThreading(Node* cur,Node*& prev)//中序线索化调用函数
{
if (cur == NULL)
return;
_InOrderThreading(cur->_leftchild, prev);
if (cur->_leftchild == NULL)//线索化左
{
cur->_leftTag = THREAD;
cur->_leftchild = prev;
}
if (prev && prev->_rightchild == NULL)//线索化右
{
prev->_rightTag = THREAD;
prev->_rightchild = cur;
}
prev = cur;
_InOrderThreading(cur->_rightchild, prev);
}
Node* _CreateTree(T* a, size_t n, const T& invalid, size_t& index)//构造函数调用函数
{
Node* root = NULL;
if ((index < n) && (a[index] != invalid))
{
root = new Node(a[index]);
root->_leftchild = _CreateTree(a, n, invalid, ++index);
root->_rightchild = _CreateTree(a, n, invalid, ++index);
}
return root;
}
protected:
Node* _root;
};
void BinaryTreeThdTest()
{
int a1[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTreeThd<int> t1(a1, (sizeof(a1) / sizeof(a1[0])), '#');
BinaryTreeThd<int> t2(a1, (sizeof(a1) / sizeof(a1[0])), '#');
BinaryTreeThd<int> t3(a1, (sizeof(a1) / sizeof(a1[0])), '#');
t1.InOrderThreading();
t1.InOrderThd();
t2.PrevOrderThreading();
t2.PrevOrderThd();
t3.PostOrderThreading();
}
int main()
{
BinaryTreeThdTest();
return 0;
}