从二叉树的遍历我们可以得知:遍历二叉树是以一定规则将二叉树中结点排成一个线性序列,得到二叉树中的结点的前序序列或中序序列或后序序列。其实质上市对一个非线
性结构进行线性化操作,使得每个结点(除去第一个和最后一个)在这些线性序列中有接近有一个直接的前驱后继。
但是,我们之前写的二叉树结构只能找到节点的做孩子和右孩子的信息,而不能直接得到结点在任一序列中的前驱和后继信息,而这种信息只有在遍历动态中得到。
那么,如何来保存这种在遍历过程中得到的信息呢?
由于在有n个结点的二叉树中必定有n+1个空链域。那么我们就利用这些空链域来存放结点的前驱和后继的信息。
规则如下:
1、首先增加两个标志域:
typedef enum{LINK,TREAD}Tag;
2、若结点有左子树,则其left域指向其左孩子,否则令left指向其后继。并修改标志域修改为TREAD。
若结点有右子树,则其right域指向其左孩子,否则令right指向其后继。并修改标志域修改为TREAD。
#ifndef _TREADBINTREE_H
#define _TREADBINTREE_H
#include"AllHead.h"
template<class T>
class TreadBinTree;
typedef enum{LINK,TREAD}Tag;
template<class T>
class BinTreeNode
{
friend class TreadBinTree<T>;
private:
BinTreeNode<T> *left;
BinTreeNode<T> *right;
T data;
Tag ltag;
Tag rtag;//加入两个标志
public:
BinTreeNode()
{
left = NULL;
right = NULL;
ltag = LINK;
rtag = LINK;
}
BinTreeNode(T d):data(d)
{
left = NULL;
right = NULL;
ltag = LINK;
rtag = LINK;
}
T getData(){return data;}
};
template<class T>
class TreadBinTree
{
public:
BinTreeNode<T> *root;
char flag;
public:
TreadBinTree()
{
root = NULL;
flag = '#';
}
public:
void create_Bintree()//-------------------------------------创建一棵二叉树
{
create_Bintree(root);
}
void create_inTreadBinTree()//------------------------------中序线索化
{
BinTreeNode<T> *pre = NULL;
create_inTreadBinTree(root,pre);
pre->right = NULL;
pre->rtag = TREAD;
}
void create_preTreadBinTree()//-----------------------------前序线索化
{
BinTreeNode<T> *pre = NULL;
if(root!=NULL)
{
create_preTreadBinTree(root,pre);
pre->right = NULL;
pre->rtag = TREAD;
}
}
void create_postTreadBinTree()//----------------------------后序线索化
{
BinTreeNode<T> *pre = NULL;
if(root!=NULL)
{
create_postTreadBinTree(root,pre);
}
}
public: //----------------------------------------------中序线索化的一些功能实现
BinTreeNode<T>* findfirst()//--------------------------------找头
{
return findfirst(root);
}
BinTreeNode<T>* findlast()//---------------------------------找尾
{
return findlast(root);
}
BinTreeNode<T>* findnext(BinTreeNode<T> *cur)//--------------找下一个
{
return findnext(root,cur);
}
BinTreeNode<T>* findprev(BinTreeNode<T> *cur)//--------------找上一个
{
return findprev(root,cur);
}
void InOrder()//中序线索化的中序遍历
{
InOrder(root);
}
void PreOrder()//前序线索化的前序遍历
{
PreOrder(root);
}
protected:
void PreOrder(BinTreeNode<T> *&p)
{
if(p == NULL)
return;
BinTreeNode<T> *cur = p;
cout<<cur->data<<"-->";
while(cur)
{
while(cur->ltag == LINK)
{
cur = cur->left;
cout<<cur->data<<"-->";
}
while(cur->rtag == TREAD)
{
cur = cur->right;
if(cur == NULL)
{
cout<<"NULL";
break;
}
else
cout<<cur->data<<"-->";
}
if(cur != NULL)
{
if(cur->ltag == TREAD)
{
cur = cur->right;
cout<<cur->data<<"-->";
}
}
}
}
void InOrder(BinTreeNode<T> *&p)
{
if(p == NULL)
return;
BinTreeNode<T> *cur = p;
while(cur)
{
while(cur->ltag == LINK)
{
cur = cur->left;
}//找到最左边的头
cout<<cur->data<<"-->";//然后输出
if(cur->right)//------->必须有这句判断否则会出现访问冲突
{
while(cur->rtag == TREAD)
{
cur = cur->right;
cout<<cur->data<<"-->";
}
}
cur = cur->right;
}
}
BinTreeNode<T>* findprev(BinTreeNode<T> *t,BinTreeNode<T> *cur)
{
if(t == NULL||cur == NULL)
return NULL;
if(cur->ltag == TREAD)
return cur->left;
return findlast(cur->left);
}
BinTreeNode<T>* findnext(BinTreeNode<T> *t,BinTreeNode<T> *cur)
{
if(t == NULL||cur == NULL)
return NULL;
if(cur->rtag == TREAD)
return cur->right;
return findfirst(cur->right);
}
BinTreeNode<T>* findlast(BinTreeNode<T> *t)
{
if(t == NULL)
return NULL;
while(t->rtag == LINK)
t = t->right;
return t;
}
BinTreeNode<T>* findfirst(BinTreeNode<T>*t)
{
if(t == NULL)
return NULL;
while(t->ltag == LINK)
t=t->left;
return t;
}
void create_Bintree(BinTreeNode<T> *&t)
{
T input;
cin>>input;
if(input == flag)
{
t = NULL;
}
else
{
// t = new BinTreeNode<T>;
// t->data = input;
t = new BinTreeNode<T>(input);
create_Bintree(t->left);
create_Bintree(t->right);
}
}
void create_preTreadBinTree(BinTreeNode<T> *&bt,BinTreeNode<T> *&pre)
{
if(bt == NULL)
return;
if(bt->left == NULL)
{
bt->left = pre;
bt->ltag = TREAD;
}
if(pre && pre->right==NULL)
{
pre->rtag = TREAD;
pre->right = bt;
}
pre = bt;
if(bt->ltag == LINK)
create_preTreadBinTree(bt->left,pre);
if(bt->rtag == LINK)
create_preTreadBinTree(bt->right,pre);
}
void create_inTreadBinTree(BinTreeNode<T> *&bt,BinTreeNode<T> *&pre)
{
if(bt == NULL)
return;
create_inTreadBinTree(bt->left,pre);//一直递归到最左边
if(bt->left == NULL) //给最左边的结点的前驱一定是空
{
bt->ltag = TREAD; //给他标记为线索化
bt->left = pre; //因为他是中序的头,并没有前驱。
}
if(pre!=NULL&&pre->right == NULL)
{
pre->rtag = TREAD;
pre->right = bt;
}
pre = bt;
create_inTreadBinTree(bt->right,pre);
}
void create_postTreadBinTree(BinTreeNode<T> *&bt,BinTreeNode<T> *&pre)
{
if (bt == NULL)
{
return;
}
create_postTreadBinTree(bt->left, pre);
create_postTreadBinTree(bt->right, pre);
if (bt->left == NULL)
{
bt->left = pre;
bt->ltag = TREAD;
}
if (pre&&pre->right == NULL)
{
pre->rtag = TREAD;
pre->right = bt;
}
pre = bt;
}
};
#include"treadbintree.h"
//ABC##DE##F##G#H##
int main()
{
BinTreeNode<char> *put ;
TreadBinTree<char> mytree;
mytree.create_Bintree(); //先创建一棵普通的二叉树
// mytree.create_inTreadBinTree(); //将二叉树线索化(中序)
mytree.create_preTreadBinTree(); //将二叉树线索化(前序)
// mytree.create_postTreadBinTree(); //将二叉树线索化(后序)
put = mytree.findfirst();
cout<<(*put).getData()<<endl;
put = mytree.findlast();
cout<<(*put).getData()<<endl;
put = mytree.findprev(put);
put = mytree.findprev(put);//A
put = mytree.findprev(put);
put = mytree.findprev(put);//D
put = mytree.findprev(put);
// put = mytree.findparent(put);
// put = mytree.findnext(put);
if(put != NULL)//一定要加这个判断条件的,不然如果找的最后一个节点的下一个会出现访问冲突
cout<<(*put).getData()<<endl;
else
cout<<"NULL"<<endl;
// mytree.InOrder();
mytree.PreOrder();
return 0;
}