void BinTree<Elem>::Create(BinTreeNodeT<Elem> *Troot)
{
char ch;
cin>>ch;
if(ch=='$')
Troot=NULL;
else
{
Troot=new BinTreeNodeT<Elem>(ch,NULL,NULL);
Create(Troot->left);
Create(Troot->right);
}
}
可以看出这个算法的创建二叉树。可以通过Troot返回根结点。就可以创建二叉树了,但是如果你真正去试过的话。就会发现你通过Troot作为根结点进行遍历打印的时候确不能打印。甚至什么都没有啊,你看自己的程序再去推感觉真的没有错啊,怎么会没有数据呢?这个问题当时也困住我了,但是后来我用VC调试的时候发现Troot从创建的函数出来Troot==NULL所有在打印时候根本就不可能的。为什么会这样呢?我再通过调试发现在函数最后递归出来时。Troot就变成NULL了,仔细看看函数递归的过程。你就能看到他其中是怎么样变。递归是系统自动调用栈的过程。本想它最后出栈应该是根结点啊。怎么会出现NULL呢?原因就是在起用递归的第一步是函数void BinTree<Elem>::Create(BinTreeNodeT<Elem> *Troot)。其中Troot在初始状态是NULL所有首先是把NULL压入栈。然后在把根结点压入栈。整个过程是把二叉树建立了,但是最后所有入栈的结点再依次出栈。然而你没忘记的话最后的就是NULL出栈。所有Troot变成NULL了。二叉树建立了,但是根结点找不着了,我急了,怎么去找呢?最后我还是找不到。不知道用什么方法。有知道的同学可以告诉我!!后来我就把这个程序改了,变成下面的样子。
BinTreeNodeT<Elem>* BinTree<Elem>::Create()
{
BinTreeNodeT<Elem>* T;
char p;
cin>>p;
if(p=='$')
T=NULL;
else
{
T=new BinTreeNodeT<Elem>(p,NULL,NULL);
T->left=Create();
T->right=Create();
}
return T;
}
变成这个样子之后我发现可以了,最后返回的T就是根结点了,仔细想这是为什么呢?其实你再回头我开始说的递归过程栈在函数中是怎么样的。就知道了,因为这里的创建函数没有参数了,所以最开始入栈的就是根结点了。就是这样。等到所有的递归完成。函数的返回的就是根结点了。问题就解决了。
所以我觉得自己在学习和编程过程中善于利用我们的编程工具能解决很多问题和学习一些自己不理解的变量和函数的内部变化情况。特别是指针的跟踪。能很多的问题不需要问别人和查书。自己利用编程工具就能知道的。下面有我编的一个完整的程序。
#include <iostream>
using namespace std;
template<class Elem>
class BinTreeNodeT
{
public:
BinTreeNodeT *left;
BinTreeNodeT *right;
Elem data;
BinTreeNodeT(Elem dataval,BinTreeNodeT *l=NULL,BinTreeNodeT *r=NULL)
{
data=dataval;
left=l;
right=r;
}
BinTreeNodeT(BinTreeNodeT *l=NULL,BinTreeNodeT *r=NULL)
{
left=l;
right=r;
}
Elem GetVal()
{
return data;
}
BinTreeNodeT* GetLeft()
{
return left;
}
BinTreeNodeT* GetRight()
{
return right;
}
void SetLeft(BinTreeNodeT *T)
{
left=T;
}
void SetRight(BinTreeNodeT *T)
{
right=T;
}
};
template <class Elem>
class BinTree
{
private:
BinTreeNodeT<Elem> *Troot;
public:
BinTree()
{
Troot=NULL;
}
~BinTree()
{
DeleteTree(Troot);
}
BinTreeNodeT<Elem> *GetRoot()
{
return Troot;
}
BinTreeNodeT<Elem>* Create();
void print(BinTreeNodeT<Elem> *);
void DeleteTree(BinTreeNodeT<Elem> *);
};
template<class Elem>
BinTreeNodeT<Elem>* BinTree<Elem>::Create()
{
BinTreeNodeT<Elem>* T;
char p;
cin>>p;
if(p=='$')
T=NULL;
else
{
T=new BinTreeNodeT<Elem>(p,NULL,NULL);
T->left=Create();
T->right=Create();
}
return T;
}
template<class Elem>
void BinTree<Elem>::print(BinTreeNodeT<Elem> *root)
{
if(root!=NULL)
{
print(root->GetLeft());
print(root->GetRight());
cout<<root->GetVal()<<" ";
}
}
template<class Elem>
void BinTree<Elem>::DeleteTree(BinTreeNodeT<Elem> * root)
{
if(root!=NULL)
{
DeleteTree(root->GetLeft());
DeleteTree(root->GetRight());
delete root;
}
}
int main()
{
BinTree<char> A;
BinTreeNodeT<char> *T;
cout<<"Enter the Tree value:"<<endl;
cout<<"Enter 15 char:"<<endl;
T=A.Create();
cout<<"Print all the char: ";
A.print(T);
return 0;
}
这里只是我个人的理解。有错的地方请高手帮我纠正过来。谢谢。