今天做编译原理的由正则表达式生成最小DFA需要用到二叉树结构。于是回顾了一下二叉树的建立。
今天很惨,我记得以前对于二叉树的建立很熟很熟,并且我还赞叹过利用前序建立树的巧妙。可是今天当我想前序建立树时,却死活建不出来!我只记得了这几步:
if(ch=='#')
{
p=NULL;
return ;
}
p->value=ch;
creatTree(p->lnode);
creatTree(p->rnode);
先介绍一下前序建立二叉树的思想。如图1所示的二叉树
其中除‘#’以外的节点是真实的二叉树,也就是需要我们构造的二叉树。现在将每个叶子节点的空子节点用‘#’节点填充,我们姑且称之为#扩展二叉树。然后写出#扩展二叉树的前序遍历:ab#d##c##,这便是我们程序的输入。程序思想是,遇到‘#’便将p赋NULL,如果不是‘#’,就malloc(sizeof(Treenode)),将值赋予Treenode,然后creatTree(p->lnode);creatTree(rnode);
以下为生成树代码段(注:有误!!)
#include
#include
#include
//定义树节点的结构体
typedef struct Tnode
{
struct Tnode *lnode;
struct Tnode *rnode;
char value;
}Tnode;
Tnode* root=NULL;
char ch;
//创建二叉树
void creatTree(Tnode* p)
{
scanf("%c",&ch);
if(ch=='#'){
p=NULL;
return ;
}
p=(Tnode*)malloc(sizeof(Tnode));
p->value=ch;
creatTree( p->lnode);
creatTree(p->rnode);
return ;
}
//前序遍历二叉树
void displayTree(Tnode* p)
{
if(p==NULL) return ;
displayTree(p->lnode);
printf("%c",p->value);
displayTree(p->rnode);
return ;
}
//销毁二叉树,回收分配的内存单元
void destroyTree(Tnode* p)
{
if(p==NULL) return;
destroyTree(p->lnode);
destroyTree(p->rnode);
free(p);
}
int main(){
creatTree(root);
displayTree(root);
destroyTree(root);
getch();
return 1;
}
#include
#include
#include
//定义树节点的结构体
typedef struct Tnode
{
struct Tnode *lnode;
struct Tnode *rnode;
char value;
}Tnode;
Tnode* root=NULL;
char ch;
//创建二叉树
void creatTree(Tnode* &p) //添加了引用&
{
scanf("%c",&ch);
if(ch=='#'){
p=NULL;
return ;
}
p=(Tnode*)malloc(sizeof(Tnode));
p->value=ch;
creatTree( p->lnode);
creatTree(p->rnode);
return ;
}
//前序遍历二叉树
void displayTree(Tnode* p)
{
if(p==NULL) return ;
displayTree(p->lnode);
printf("%c",p->value);
displayTree(p->rnode);
return ;
}
//销毁二叉树,回收分配的内存单元
void destroyTree(Tnode* p)
{
if(p==NULL) return;
destroyTree(p->lnode);
destroyTree(p->rnode);
free(p);
}
int main(){
creatTree(root);
displayTree(root);
destroyTree(root);
getch();
return 1;
}
我在函数形参前加了取址符号&,表示我引用了实参。
也就是说,我传入的是指向这个变量存储位置的指针,函数可以通过这个指针修改实参的值,所以我对加了引用的形参修改便修改了实参的值。
重点在于,指针变量也是变量,如果要在函数中想要使对于形参的值修改对应到实参的值修改,必须加引用&。
关于利用中序、后序建立二叉树的方法,改日再探索。