二叉树线索化
二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只 能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。
enum PointerTag {THREAD, LINK};
template <class T>
struct BinaryTreeNode_Thd
{ T _data ; // 数据
BinaryTreeNode_Thd<T >* _left; // 左孩子
BinaryTreeNode_Thd<T >* _right; // 右孩子
PointerTag _leftTag ; // 左孩子线索标志
PointerTag _rightTag ; // 右孩子线索标志
};
测试用例
int array [10] = {1, 2, 3, '#', '#', 4, '#' , '#', 5, 6};
int array[15] = {1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8};
创建二叉树
Node* _CreateTree(T*a,size_t size,size_t &index,const T& invalid)
{
Node* root = NULL;
if(index<size && a[index] != invalid)
{
root =new Node(a[index]);
root->_left=_CreateTree(a,size,++index,invalid);
root->_right=_CreateTree(a,size,++index,invalid);
}
return root;
}
前序线索化
void _PrevOrderThreading(Node*cur,Node*& prev)//线索化遍历//可循环,遇到一个节点找前驱或后继
{
if(cur==NULL)
return ;
while(cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
while(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 _PrevOverThd(Node*cur)
{
if(cur==NULL)
return ;
while(cur)
{
while(cur->_leftTag == LINK)
{
cout<<cur->_data<<" ";
cur = cur->_left;
}
cout<<cur->_data<<" ";
cur = cur->_right;
}
cout<<endl;
}
中序线索化
void _InorderThreading(Node* root,Node*& prev)
{
if(root==NULL)
return ;
_InorderThreading(root->_left,prev);
//左子树
if(root->_left==NULL)
{
root->_leftTag = THREAD;
root->_left = prev;
}
//上一个节点
if(prev&&prev->_right==NULL)
{
prev->_rightTag = THREAD;<pre class="html" name="code"> }
}
中序遍历
void _InOrderThd(Node*root)
{
if(cur==NULL)
return ;
while(cur)
{
//找最左节点
if(cur&&cur->_leftTag==LINK)
{
cur = cur->_left;
}
cout<<cur->_data<<" ";
while(cur->_rightTag==THREAD)
{
cur = cur->_right;
cout<<cur->_data<<" ";
}
if(cur->_rightTag==LINK)
cur = cur->_right;
}
cout<<endl;
}
后序线索化
void _PostorderThreading(Node* root,Node* &prev)
{
if(root==NULL)
return;
_PostorderThreading(root->_left,prev);
_PostorderThreading(root->_right,prev);
if(root->_left==NULL)
{
root->_leftTag=THREAD;
root->_left=prev;
}
if(prev&&prev->_right==NULL)
{
prev->_rightTag=THREAD;
prev->_right=root;
}
prev=root;
}
详细代码实现
#include<iostream>
#include<stdlib.h>
#include<assert.h>
using namespace std;
enum Tag
{
LINK ,THREAD
};
template <class T>
struct BinaryTreeThNode
{
T _data;
BinaryTreeThNode* _left;
BinaryTreeThNode* _right;
Tag _leftTag;
Tag _rightTag;
BinaryTreeThNode(const T& x)
:_data(x)
,_left(NULL)
,_right(NULL)
,_leftTag(LINK)
,_rightTag(LINK)
{}
};
template <class T>
class BinaryTree
{
typedef BinaryTreeThNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(T *a,size_t size,const T&invalid)
{
assert(a);
size_t index=0;
_root= _CreateTree(a,size,index,invalid);
}
void InorderThreading()
{
Node* prev=NULL;
_InorderThreading(_root,prev);
}
void InOrderThd()
{
_InOrderThd(_root);
}
void PrevOrderThreading()
{
Node* prev = NULL;
_PrevOrderThreading(_root,prev);
}
void PrevOverThd()
{
_PrevOverThd(_root);
}
void PostorderThreading()
{
Node* prev = NULL;
return _PostorderThreading(_root,prev);
}
void PostorderThd()
{
_PostorderThd(_root);
}
protected:
Node* _CreateTree(T*a,size_t size,size_t &index,const T& invalid)
{
Node* root = NULL;
if(index<size && a[index] != invalid)
{
root =new Node(a[index]);
root->_left=_CreateTree(a,size,++index,invalid);
root->_right=_CreateTree(a,size,++index,invalid);
}
return root;
}
void _PrevOrderThreading(Node*cur,Node*& prev)//线索化遍历//可循环,遇到一个节点找前驱或后继
{
if(cur==NULL)
return ;
while(cur->_left == NULL)
{
cur->_leftTag = THREAD;
cur->_left = prev;
}
while(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 _PrevOverThd(Node*cur)
{
if(cur==NULL)
return ;
while(cur)
{
while(cur->_leftTag == LINK)
{
cout<<cur->_data<<" ";
cur = cur->_left;
}
cout<<cur->_data<<" ";
cur = cur->_right;
}
cout<<endl;
}
void _InorderThreading(Node* root,Node*& prev)
{
if(root==NULL)
return ;
_InorderThreading(root->_left,prev);
//左子树
if(root->_left==NULL)
{
root->_leftTag = THREAD;
root->_left = prev;
}
//上一个节点
if(prev&&prev->_right==NULL)
{
prev->_rightTag = THREAD;
prev->_right = root;
}
prev = root;
_InorderThreading(root->_right,prev);
}
void _InOrderThd(Node*root)
{
if(cur==NULL)
return ;
while(cur)
{
//找最左节点
if(cur&&cur->_leftTag==LINK)
{
cur = cur->_left;
}
cout<<cur->_data<<" ";
while(cur->_rightTag==THREAD)
{
cur = cur->_right;
cout<<cur->_data<<" ";
}
if(cur->_rightTag==LINK)
cur = cur->_right;
}
cout<<endl;
}
void _PostorderThreading(Node* root,Node* &prev)
{
if(root==NULL)
return;
_PostorderThreading(root->_left,prev);
_PostorderThreading(root->_right,prev);
if(root->_left==NULL)
{
root->_leftTag=THREAD;
root->_left=prev;
}
if(prev&&prev->_right==NULL)
{
prev->_rightTag=THREAD;
prev->_right=root;
}
prev=root;
}
/*???*///void _PostorderThd(Node*root)//线索化遍历//可循环,遇到一个节点找前驱或后继
// {
// Node* cur =root;
// while(cur)
// {
// while(cur&&cur->_leftTag == LINK)
// {
// cout<<cur->_data<<" ";
// cur = cur->_left;
// }
// cout<<cur->_data<<" ";
// cur = cur->_right;
// }
// cout<<endl;
//
//}
private:
Node* _root;
};
void TestBinaryTreeTh()
{
int array2[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
BinaryTree<int> tree(array2,15,'#');
/*tree.InorderThreading();
tree.InOrderThd();*/
/*tree.PrevOrderThreading();
tree.PrevOverThd();*/
/*tree.PostorderThreading();
tree.PostorderThd();*/
}
int main()
{
TestBinaryTreeTh();
system("pause");
return 0;
}