线索二叉树,我写过的比较恶心的数据结构之一。我一直认为线索化应该是对二叉树的一个操作。可是,线索二叉树与普通的二叉树却实在大有不同。算了,不说了,上代码!
#include <iostream>
using namespace std;
#ifndef TREENODE_H_INCLUDED
#define TREENODE_H_INCLUDED
enum PointerTag
{
Link,
Thread
};
template <class ElemType>
class TreeNode
{
private:
TreeNode* lchild;
TreeNode* rchild;
TreeNode* parent;
PointerTag ltag;
PointerTag rtag;
public:
ElemType data;
TreeNode(const ElemType& item,TreeNode* lptr=NULL,TreeNode* rptr=NULL,PointerTag lt=Link,PointerTag rt=Link,TreeNode* par=NULL):
lchild(lptr),rchild(rptr),parent(par),ltag(lt),rtag(rt),data(item){ }
~TreeNode(){ }
TreeNode* LeftChild(){return lchild;}
TreeNode* RightChild(){return rchild;}
void SetLeftChild(TreeNode* chd){lchild=chd;}
void SetRightChild(TreeNode* chd){rchild=chd;}
void SetParent(TreeNode* par){parent=par;}
TreeNode* Parent(){return parent;}
PointerTag LeftTag(){return ltag;}
PointerTag RightTag(){return rtag;}
void SetLeftTag(PointerTag tag){ltag=tag;}
void SetRightTag(PointerTag tag){rtag=tag;}
};
#endif // TREENODE_H_INCLUDED
#include <iostream>
#include <list>
#include "treenode.h"
using namespace std;
#ifndef TREELIB_H_INCLUDED
#define TREELIB_H_INCLUDED
template <class ElemType>
TreeNode<ElemType>* GetTreeNode(ElemType item,TreeNode<ElemType>* lptr,TreeNode<ElemType>* rptr)
{
TreeNode<ElemType>* p=new TreeNode<ElemType>(item,lptr,rptr,Link,Link);
if(lptr)
{
lptr->SetParent(p);
}
if(rptr)
{
rptr->SetParent(p);
}
return p;
}
template <class ElemType>
void FreeNode(TreeNode<ElemType>* t)
{
delete t;
}
template <class ElemType>
void InThreading(TreeNode<ElemType> * t,TreeNode<ElemType>* &pre)
{
if(t)
{
InThreading(t->LeftChild(),pre);
if(!t->LeftChild())
{
t->SetLeftTag(Thread);
t->SetLeftChild(pre);
}
if(!pre->RightChild())
{
pre->SetRightTag(Thread);
pre->SetRightChild(t);
}
pre=t;
InThreading(t->RightChild(),pre);
}
}
template <class ElemType>
bool InorderThreading(TreeNode<ElemType> *t,TreeNode<ElemType>* &thrt)
{
thrt=new TreeNode<ElemType>(' ');
TreeNode<ElemType>* pre;
if(!thrt)
{
return false;
}
thrt->SetLeftTag(Link);
thrt->SetRightTag(Thread);
thrt->SetRightChild(thrt);
if(!t)
{
thrt->SetLeftChild(thrt);
}
else
{
thrt->SetLeftChild(t);
pre=thrt;
InThreading(t,pre);
pre->SetRightTag(Thread);
pre->SetRightChild(thrt);
thrt->SetRightChild(pre);
}
return true;
}
template <class ElemType>
void PreThreading(TreeNode<ElemType>* t,TreeNode<ElemType>* &pre)
{
if(t)
{
if(!t->LeftChild())
{
t->SetLeftTag(Thread);
t->SetLeftChild(pre);
}
if(!pre->RightChild())
{
pre->SetRightTag(Thread);
pre->SetRightChild(t);
}
pre=t;
if(t->LeftTag()==Link)
{
PreThreading(t->LeftChild(),pre);
}
if(t->RightTag()==Link)
{
PreThreading(t->RightChild(),pre);
}
}
}
template <class ElemType>
bool PreorderThreading(TreeNode<ElemType> *t,TreeNode<ElemType>* &thrt)
{
thrt=new TreeNode<ElemType>(' ');
TreeNode<ElemType>* pre;
if(!thrt)
{
return false;
}
thrt->SetLeftTag(Link);
thrt->SetRightTag(Thread);
thrt->SetRightChild(thrt);
if(!t)
{
thrt->SetLeftChild(thrt);
}
else
{
thrt->SetLeftChild(t);
pre=thrt;
PreThreading(t,pre);
pre->SetRightTag(Thread);
pre->SetRightChild(thrt);
thrt->SetRightChild(pre);
}
return true;
}
template <class ElemType>
void PostThreading(TreeNode<ElemType> *t,TreeNode<ElemType>* &pre)
{
if(t)
{
PostThreading(t->LeftChild(),pre);
PostThreading(t->RightChild(),pre);
if(!t->LeftChild())
{
t->SetLeftTag(Thread);
t->SetLeftChild(pre);
}
if(!pre->RightChild())
{
pre->SetRightTag(Thread);
pre->SetRightChild(t);
}
pre=t;
}
}
template <class ElemType>
bool PostorderThreading(TreeNode<ElemType> *t,TreeNode<ElemType>* &thrt)
{
thrt=new TreeNode<ElemType>(' ');
TreeNode<ElemType>* pre;
if(!thrt)
{
return false;
}
thrt->SetLeftTag(Link);
thrt->SetRightTag(Thread);
thrt->SetRightChild(thrt);
if(!t)
{
thrt->SetLeftChild(thrt);
}
else
{
thrt->SetLeftChild(t);
pre=thrt;
PostThreading(t,pre);
thrt->SetRightChild(pre);
}
return true;
}
template <class ElemType>
int CountLeaf(TreeNode<ElemType>* t)
{
if(t)
{
if(t->LeftTag()==Thread&&t->RightTag()==Thread)
{
return 1;
}
if(t->LeftTag()==Link&&t->RightTag()==Thread)
{
return CountLeaf(t->LeftChild());
}
if(t->LeftTag()==Thread&&t->RightTag()==Link)
{
return CountLeaf(t->RightChild());
}
return CountLeaf(t->LeftChild())+CountLeaf(t->RightChild());
}
else
{
return 0;
}
}
template <class ElemType>
int CountNode(TreeNode<ElemType>* t)
{
if(t)
{
if(t->LeftTag()==Thread&&t->RightTag()==Thread)
{
return 1;
}
if(t->LeftTag()==Link&&t->RightTag()==Thread)
{
return CountNode(t->LeftChild())+1;
}
if(t->LeftTag()==Thread&&t->RightTag()==Link)
{
return CountNode(t->RightChild())+1;
}
return CountNode(t->LeftChild())+CountNode(t->RightChild())+1;
}
else
{
return 0;
}
}
template <class ElemType>
int Depth(TreeNode<ElemType>* t)
{
int depthleft,depthright,depthval;
if(!t)
{
depthval=0;
}
else
{
if(t->LeftTag()==Link&&t->RightTag()==Link)
{
depthleft=Depth(t->LeftChild());
depthright=Depth(t->RightChild());
}
else if(t->LeftTag()==Link&&t->RightTag()==Thread)
{
depthleft=Depth(t->LeftChild());
depthright=0;
}
else if(t->LeftTag()==Thread&&t->RightTag()==Link)
{
depthleft=0;
depthright=Depth(t->RightChild());
}
else
{
depthleft=depthright=0;
}
depthval=1+(depthleft>depthright?depthleft:depthright);
}
return depthval;
}
template <class ElemType>
void DeleteTree(TreeNode<ElemType>* t)
{
if(t)
{
if(t->LeftTag()==Link)
{
DeleteTree(t->LeftChild());
}
if(t->RightTag()==Link)
{
DeleteTree(t->RightChild());
}
FreeNode(t);
}
}
template <class ElemType>
void ClearTree(TreeNode<ElemType>* &t)
{
DeleteTree(t);
t=NULL;
}
#endif // TREELIB_H_INCLUDED
#include <iostream>
#include "treenode.h"
using namespace std;
#ifndef TREESCAN_H_INCLUDED
#define TREESCAN_H_INCLUDED
template <class ElemType>
void PreorderTraverse(TreeNode<ElemType>* thrt,void (*Visit)(ElemType& e))
{
TreeNode<ElemType>* p=thrt->LeftChild();
while(p!=thrt)
{
Visit(p->data);
if(p->LeftTag()==Link)
{
p=p->LeftChild();
}
else
{
p=p->RightChild();
}
}
}
template <class ElemType>
void InorderTraverse(TreeNode<ElemType>* thrt,void (*Visit)(ElemType& e))
{
TreeNode<ElemType>* p=thrt->LeftChild();
while(p!=thrt)
{
while(p->LeftTag()==Link)
{
p=p->LeftChild();
}
Visit(p->data);
while(p->RightTag()==Thread&&p->RightChild()!=thrt)
{
p=p->RightChild();
Visit(p->data);
}
p=p->RightChild();
}
}
template <class ElemType>
void PostorderTraverse(TreeNode<ElemType>* thrt,void (*Visit)(ElemType& e))
{
TreeNode<ElemType>* p=thrt->LeftChild();
TreeNode<ElemType>* par;
while(p->LeftTag()==Link||p->RightTag()==Link)
{
while(p->LeftTag()==Link)
{
p=p->LeftChild();
}
if(p->RightTag()==Link)
{
p=p->RightChild();
}
}
while(p!=thrt)
{
Visit(p->data);
if(!p->Parent())
{
break;
}
par=p->Parent();
if(p==par->RightChild()||par->RightTag()==Thread)
{
p=par;
}
else
{
par=par->RightChild();
while(par->LeftTag()==Link||par->RightTag()==Link)
{
while(par->LeftTag()==Link)
{
par=par->LeftChild();
}
if(par->RightTag()==Link)
{
par=par->RightChild();
}
}
p=par;
}
}
}
#endif // TREESCAN_H_INCLUDED
#include <iostream>
#include <iomanip>
#include "treenode.h"
#include "treelib.h"
#include "treescan.h"
using namespace std;
void Visit(char& x)
{
cout<<x;
}
int main()
{
TreeNode<char> *root1,*root2,*root3;
TreeNode<char>* thrt;
TreeNode<char> *a,*b,*c,*d,*e,*f,*g,*h,*i;
d = GetTreeNode('D',(TreeNode<char> *)NULL,(TreeNode<char> *)NULL);
e = GetTreeNode('E',(TreeNode<char> *)NULL,(TreeNode<char> *)NULL);
b = GetTreeNode('B',(TreeNode<char> *)NULL, d);
c = GetTreeNode('C',e, (TreeNode<char> *)NULL);
a = GetTreeNode('A',b, c);
root1 = a;
InorderThreading(root1,thrt);
cout<<"after executing the function of InorderThreading, "<<endl;
cout<<"the number of leaves is "<<CountLeaf(root1)<<endl;
cout<<"the number of nodes is "<<CountNode(root1)<<endl;
cout<<"the depth of this binary tree is "<<Depth(root1)<<endl;
cout<<"InorderTraverse result: "<<endl;
InorderTraverse(thrt,Visit);
cout<<endl;
FreeNode(thrt);
ClearTree(root1);
cout<<"after executing the function of ClearTree, "<<endl;
cout<<"the number of leaves is "<<CountLeaf(root1)<<endl;
cout<<"the number of nodes is "<<CountNode(root1)<<endl;
cout<<"the depth of this binary tree is "<<Depth(root1)<<endl;
g = GetTreeNode('G',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
h = GetTreeNode('H',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
i = GetTreeNode('I',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
d = GetTreeNode('D',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
e = GetTreeNode('E',g, (TreeNode<char> *)NULL);
f = GetTreeNode('F',h, i);
b = GetTreeNode('B',d, e);
c = GetTreeNode('C',(TreeNode<char> *)NULL, f);
a = GetTreeNode('A',b, c);
root2=a;
PreorderThreading(root2,thrt);
cout<<"after executing the function of PreorderThreading, "<<endl;
cout<<"the number of leaves is "<<CountLeaf(root2)<<endl;
cout<<"the number of nodes is "<<CountNode(root2)<<endl;
cout<<"the depth of this binary tree is "<<Depth(root2)<<endl;
cout<<"PreorderTraverse result: "<<endl;
PreorderTraverse(thrt,Visit);
cout<<endl;
FreeNode(thrt);
ClearTree(root2);
cout<<"after executing the function of ClearTree, "<<endl;
cout<<"the number of leaves is "<<CountLeaf(root2)<<endl;
cout<<"the number of nodes is "<<CountNode(root2)<<endl;
cout<<"the depth of this binary tree is "<<Depth(root2)<<endl;
g = GetTreeNode('G',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
h = GetTreeNode('H',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
i = GetTreeNode('I',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
d = GetTreeNode('D',(TreeNode<char> *)NULL, g);
e = GetTreeNode('E',h, i);
f = GetTreeNode('F',(TreeNode<char>*)NULL,(TreeNode<char>*)NULL);
b = GetTreeNode('B',d, (TreeNode<char> *)NULL);
c = GetTreeNode('C',e, f);
a = GetTreeNode('A',b, c);
root3=a;
PostorderThreading(root3,thrt);
cout<<"after executing the function of PostorderThreading, "<<endl;
cout<<"the number of leaves is "<<CountLeaf(root3)<<endl;
cout<<"the number of nodes is "<<CountNode(root3)<<endl;
cout<<"the depth of this binary tree is "<<Depth(root3)<<endl;
cout<<"PostorderTraverse result: "<<endl;
PostorderTraverse(thrt,Visit);
cout<<endl;
FreeNode(thrt);
ClearTree(root3);
cout<<"after executing the function of ClearTree, "<<endl;
cout<<"the number of leaves is "<<CountLeaf(root3)<<endl;
cout<<"the number of nodes is "<<CountNode(root3)<<endl;
cout<<"the depth of this binary tree is "<<Depth(root3)<<endl;
return 0;
}
treenode.h用于定义线索二叉树的节点类,treelib.h用于实现一些线索二叉树的常用操作,比如说线索化等等,treescan.h包括了线索二叉树的先序、中序和后序遍历。