#include <iostream>
#include <malloc.h>
using namespace std;
typedef struct Tnode
{
char data;
struct Tnode* lc;
struct Tnode* rc;
/* data */
}Tnode, *Tree;
int TreeInit(Tree& T)
{
T=(Tree)malloc(sizeof(Tnode)); //开空间,创建树
if (!T) return 0; //不太懂这个是什么意思,在初始化树的函数里还需要判断T是否为空,是为了判断是否成功申请空间吗
T->lc=T->rc=NULL; //T是指针,每个父节点,就是T
return 1; //创建成功,返回1
}
int k=0;
char ch;
string Str; //预设一些参数,帮助理解
void TreeCreat(Tree&T) //创建树
{
ch=Str[k];
while(ch)
{
if(isalpha(ch)) //如果是字母
{
Tree p;
TreeInit(p);
p->data=ch;
if(k==0) T->lc=p;
else
{
if(Str[k-1]==',') //读入的字母前一个是,说明这个读入的字母是右子树,所以把新开的p赋给T->rc
{
T->rc=p;
}
else T->lc=p;
}
++k; //指向下一个字符
TreeCreat(p); //如果是字母,他就有作为父节点的可能,因此以他作为父节点,进入下一次创建树的递归
}
//现在探讨一下遇到标点符号应该如何处理
//遇到'('可以直接跳过
//遇到')',return这次递归
//但是遇到','有些难处理,因为如果(a,b),这个逗号需要return,如果是(,b),则不需要return,(a,)也不需要返回(留给右括号返回)
//总的来说,如果逗号前后没有括号,就需要返回
if(ch=='(') k+=1;
if(ch==',')
{
if(Str[k-1]=='(')
{
k+=1;
ch=Str[k];
}
else if(Str[k+1]==')')
{
k+=1;
ch=Str[k];
}
else{
k++;
ch=Str[k];
return;
}
}
if(ch==')')
{
k+=1;
ch=Str[k];
return;
}
ch=Str[k]; //重新读入字符要放最后面,因为下一次循环需要判断是否结束
}
}
int main()
{
Tree T;
TreeInit(T);
Str="A(B(,E),C(D,))";
TreeCreat(T);
return 0;
}
中间遇到的几个难点罗列如下
何时开新结点,何时return。
1、关于何时开新节点
每读到一个字母,它都有成为新节点的潜力,因此我们会递归进入,此时便是开了新节点
即使他没有子节点,我们也能在合适的时机退出,不妨碍二叉树的继续构建
2、关于何时return
显然,反复阅读理解字符串之后,总共会出现四种情况,(A,B) (A,) (A) (,B)
我们首先指定,读到右括号return一级,这是显而易见的处理方式。
然后就是对于逗号的处理,我们可以得知,(A,B)的逗号被读到时,是需要return的,但是 (A,) 和(,B)的逗号被读到时,不需要返回(因为本就没有进入下一级),此时我们需要特殊处理
if(ch==',')
{
if(Str[k-1]=='(')
{
k+=1;
ch=Str[k];
}
else if(Str[k+1]==')')
{
k+=1;
ch=Str[k];
}
else{
k++;
ch=Str[k];
return;
}
}
其中ch的赋值是可以去掉的,因为在完整代码中,while循环的最后一步也有在赋值,但是懒得去掉了(乐)。