二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。
enum PointerTag {THREAD, LINK};
template <class T>
struct BinaryTreeNode_Thd
{
T _data ; // 数据
BinaryTreeNode_Thd<T >* _left; // 左孩子
BinaryTreeNode_Thd<T >* _right; // 右孩子
PointerTag _leftTag ; // 左孩子线索标志
PointerTag _rightTag ; // 右孩子线索标志
};
代码实现:
#pragma once
#include<iostream>
#include<assert.h>
#include<stack>
using namespace std;
enum PointerTag
{
LINK,
THREAD
};
template<class T>
struct BinaryTreeNode_Thd
{
BinaryTreeNode_Thd(const T& d)
:_data(d)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
T _data;
BinaryTreeNode_Thd<T>* _left;//左孩子
BinaryTreeNode_Thd<T>* _right;//右孩子
PointerTag _leftTag;//左孩子线索化标志
PointerTag _rightTag;//右孩子线索化标志
};
template<class T>
class BinaryTreeThd
{
typedef BinaryTreeNode_Thd<T> Node;
public:
BinaryTreeThd()
:_root(NULL)
{}
BinaryTreeThd(const T* a, size_t size, const T& invalid)
{
size_t index = 0;
_root = _CreatTree(a, size, index, invalid);
}
void InOrderTheading()//中序线索化
{
Node* prev = NULL;
_InOrderTheading(_root, prev);
}
void InOrderThd()//中序遍历
{
Node* cur = _root;
while (cur)
{
while (cur != NULL&&cur->_leftTag == LINK)//找树的最左节点
{
cur = cur->_left;
}
cout << cur->_data << " ";
while (cur->_rightTag == THREAD)
{
cur = cur->_right;
cout << cur->_data << " ";
}
cur = cur->_right;
}
cout << endl;
}
void PrevOrderTheading()//前序线索化
{
Node* prev = NULL;
_PrevOrderTheading(_root, prev);
}
void PrevOrderThd()//前序遍历
{
Node* cur = _root;
while (cur)
{
while (cur&&cur->_leftTag == LINK)
{
cout << cur->_data << " ";
cur = cur->_left;
}
cout << cur->_data << " ";
cur = cur->_right;
}
cout << endl;
}
void PostOrderTheading()//后序线索化
{
Node* prev = NULL;
_PostOrderTheading(_root, prev);
}
void PostOrderThd()
{
stack<Node*> s;
Node* cur = _root;
while (cur)
{
while (cur && cur->_rightTag == LINK)
{
s.push(cur);
cur = cur->_right;
}
s.push(cur);
cur = cur->_left;
}
while (!s.empty())
{
cout << s.top()->_data << " ";
s.pop();
}
cout << endl;
}
protected:
Node* _CreatTree(const T *a, size_t size, size_t &index, const T& invalid)//建立二叉树
{
assert(a);
Node* node = NULL;
if (a[index] != invalid && index < size)
{
node = new Node(a[index]);
node->_left = _CreatTree(a, size, ++index, invalid);
node->_right = _CreatTree(a, size, ++index, invalid);
}
return node;
}
void _InOrderTheading(Node *cur, Node* &prev)//递归方法中序线索化
{
if (cur == NULL)
return;
_InOrderTheading(cur->_left, prev);
if (cur->_left == NULL)//线索化前驱
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
if (prev && prev->_right == NULL)
#include<iostream>
#include<assert.h>
#include<stack>
using namespace std;
enum PointerTag
{
LINK,
THREAD
};
template<class T>
struct BinaryTreeNode_Thd
{
BinaryTreeNode_Thd(const T& d)
:_data(d)
, _left(NULL)
, _right(NULL)
, _leftTag(LINK)
, _rightTag(LINK)
{}
T _data;
BinaryTreeNode_Thd<T>* _left;//左孩子
BinaryTreeNode_Thd<T>* _right;//右孩子
PointerTag _leftTag;//左孩子线索化标志
PointerTag _rightTag;//右孩子线索化标志
};
template<class T>
class BinaryTreeThd
{
typedef BinaryTreeNode_Thd<T> Node;
public:
BinaryTreeThd()
:_root(NULL)
{}
BinaryTreeThd(const T* a, size_t size, const T& invalid)
{
size_t index = 0;
_root = _CreatTree(a, size, index, invalid);
}
void InOrderTheading()//中序线索化
{
Node* prev = NULL;
_InOrderTheading(_root, prev);
}
void InOrderThd()//中序遍历
{
Node* cur = _root;
while (cur)
{
while (cur != NULL&&cur->_leftTag == LINK)//找树的最左节点
{
cur = cur->_left;
}
cout << cur->_data << " ";
while (cur->_rightTag == THREAD)
{
cur = cur->_right;
cout << cur->_data << " ";
}
cur = cur->_right;
}
cout << endl;
}
void PrevOrderTheading()//前序线索化
{
Node* prev = NULL;
_PrevOrderTheading(_root, prev);
}
void PrevOrderThd()//前序遍历
{
Node* cur = _root;
while (cur)
{
while (cur&&cur->_leftTag == LINK)
{
cout << cur->_data << " ";
cur = cur->_left;
}
cout << cur->_data << " ";
cur = cur->_right;
}
cout << endl;
}
void PostOrderTheading()//后序线索化
{
Node* prev = NULL;
_PostOrderTheading(_root, prev);
}
void PostOrderThd()
{
stack<Node*> s;
Node* cur = _root;
while (cur)
{
while (cur && cur->_rightTag == LINK)
{
s.push(cur);
cur = cur->_right;
}
s.push(cur);
cur = cur->_left;
}
while (!s.empty())
{
cout << s.top()->_data << " ";
s.pop();
}
cout << endl;
}
protected:
Node* _CreatTree(const T *a, size_t size, size_t &index, const T& invalid)//建立二叉树
{
assert(a);
Node* node = NULL;
if (a[index] != invalid && index < size)
{
node = new Node(a[index]);
node->_left = _CreatTree(a, size, ++index, invalid);
node->_right = _CreatTree(a, size, ++index, invalid);
}
return node;
}
void _InOrderTheading(Node *cur, Node* &prev)//递归方法中序线索化
{
if (cur == NULL)
return;
_InOrderTheading(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;
_InOrderTheading(cur->_right, prev);
}
void _PrevOrderTheading(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)
_PrevOrderTheading(cur->_left, prev);
if (cur->_rightTag == LINK)
_PrevOrderTheading(cur->_right, prev);
}
void _PostOrderTheading(Node *cur, Node* &prev)//递归方法后序线索化
{
if (cur == NULL)
return;
_PostOrderTheading(cur->_left, prev);
_PostOrderTheading(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;
}
private:
Node* _root;
};
void Test()
{
int array1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTreeThd <int>t1(array1, 10, '#');
t1.InOrderTheading();//中序
t1.InOrderThd();
//t1.PrevOrderTheading();//前序
//t1.PrevOrderThd();
//t1.PostOrderTheading();//后序
//t1.PostOrderThd();
}
//因此后继通过线索化下各节点的前驱时进行线索化
{
prev->_rightTag = THREAD;
prev->_right = cur;
}
prev = cur;
_InOrderTheading(cur->_right, prev);
}
void _PrevOrderTheading(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)
_PrevOrderTheading(cur->_left, prev);
if (cur->_rightTag == LINK)
_PrevOrderTheading(cur->_right, prev);
}
void _PostOrderTheading(Node *cur, Node* &prev)//递归方法后序线索化
{
if (cur == NULL)
return;
_PostOrderTheading(cur->_left, prev);
_PostOrderTheading(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;
}
private:
Node* _root;
};
void Test()
{
int array1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
BinaryTreeThd <int>t1(array1, 10, '#');
t1.InOrderTheading();//中序
t1.InOrderThd();
//t1.PrevOrderTheading();//前序
//t1.PrevOrderThd();
//t1.PostOrderTheading();//后序
//t1.PostOrderThd();
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"BinaryTreeThreading.h"
int main()
{
Test();
system("pause");
return 0;
}
#include"BinaryTreeThreading.h"
int main()
{
Test();
system("pause");
return 0;
}