此次重点在于 二叉树的结构体构造(指针的大量练习),数组方式构造(简易)
建树的输入方式为,
(11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) ()
()表示结束LL表示从根节点开始向右移两次,并且同时延伸 (5,)表示根节点
首先还是先来比较麻烦的结构体构造方法,但是看起来很高端。
char s[100];//保存输入 int Failed=0,cnt=0; //表明是否输入有误 cnt是计数器 记录节点数目 //定义结构体 typedef struct Tnode //自定义一个结构体 { int hv;// have been valued int v;//存储节点数值 struct Tnode *l,*r;//左右儿子 都是指向Tnode的指针 此时不能用Node*是因为Node还没有定义完全 } Node;//命名在Node //发现了 二叉树的定义过程中其实用到了递归的方法 Node* root;//此为根节点 //此函数用来创建新node且为之申请动态内存 stdlib.h Node* newnode() { Node* u = (Node*)malloc(sizeof(Node)) ;//将申请来的内存格式化 if(u != NULL)//防止是非法内存 { u->hv=0;//为u初始化 u->l=u->r=NULL;//还无左右儿子 连续赋值 必须赋值为空 否则后续无法判断是否为空 } return u;//返回新建的节点 } //向已有的树上添加节点 v来赋值 s来确定节点位置 void addnode(int v,char *s) { //按照移动序列行走 *s =="LL)" int len=strlen(s);//用来做循环控制 Node* u =root;//起点是root根节点 每一次寻找位置都要从根节点开始 for(int i=0;i<len;i++) { if(s[i]=='L') { if(u->l==NULL) u->l=newnode();//找到了空节点,说明要进行延伸 u=u->l;//向左走 //延伸了之后才能移动 }else if(s[i]=='R') { if(u->r==NULL) u->r=newnode(); u=u->r;//向左走 } } <span style="white-space:pre"> </span>//此时已经找到了要赋值的节点了 if(u->hv) Failed=1;//如果输入有误则报错 else { u->v=v; u->hv=1; } } //读入并建树 int read() { Failed=0;//每次新建树时要重置 remove_tree(root) ;//释放原有内存 root = newnode();//为根节点进行初始化 ,建立一棵新树 主要是为了覆盖上一次的树 for(;;)//不断地读入 { if(scanf("%s",s)!=1) return 0;//表示输入结束 //strcmp 的返回值比较奇葩 若str1=str2,则返回零 说明完全相同 if(!strcmp(s,"()")) break;//如果读入的是()就表示完成了一次输入 return 1 int v;//存储节点值 sscanf(&s[1],"%d",&v);//&s[1] 返回的是从s的第二个字符到结尾 的数组 sscanf 从字符数组中读入v addnode(v,strchr(s,',')+1);//strchr(s,',')返回的正好是','的指针,再+1 } return 1; } void remove_tree(Node* u) { if(u==NULL) return;//走到某一个叶子时就return //利用递归循环删除 remove_tree(u->l); remove_tree(u->r); free(u); }
此种方法的优点是比较易懂,后序过程时思考难度下降,并且是动态内存,所以不用管数据的大小
还有一种避免指针的方式,就是用数组来进行建树。
const int root=1; int left[10000],right[10000],cnt; int nodes[10000]={0}; //left和right只用来记录节点之间的父子关系,且序号是按照输入顺序进行的 //真正的数据值存储在nodes里 bool failed = false; char s[100]; //建立一棵新树, void newtree() { left[root]=right[root]=0; cnt=1; memset(nodes,0,sizeof(nodes)); } int newnode() { <span style="white-space:pre"> </span>int u = ++cnt;//使cnt增加1 表明有了一个新的节点 <span style="white-space:pre"> </span>left[u]=right[u]=0; <span style="white-space:pre"> </span>return u;//返回u } void addnode(int v,char *s)//值v s= LL) { <span style="white-space:pre"> </span>int len= strlen(s); <span style="white-space:pre"> </span>int t=root; <span style="white-space:pre"> </span>for(int i=0;i<len;i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>//先找到节点位置,如果遇到空就建立新节点 <span style="white-space:pre"> </span>if(s[i]=='L') <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if(left[t]==0) <span style="white-space:pre"> </span>left[t]=newnode();//如果当前的左边是空的就建立一个节点 <span style="white-space:pre"> </span>t=left[t];//向左走 <span style="white-space:pre"> </span>}else <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if(s[i]=='R') <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if(right[t]==0) <span style="white-space:pre"> </span>right[t]=newnode();//如果当前的左边是空的就建立一个节点 <span style="white-space:pre"> </span>t=right[t];//向左走 <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if(nodes[t]) <span style="white-space:pre"> </span>failed = true; <span style="white-space:pre"> </span>else <span style="white-space:pre"> </span>nodes[t]=v; <span style="white-space:pre"> </span> } int read() { <span style="white-space:pre"> </span>newtree(); <span style="white-space:pre"> </span>while(scanf("%s",s)==1) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if(!strcmp(s,"()")) <span style="white-space:pre"> </span>return 1;//结束 <span style="white-space:pre"> </span>int d=0; <span style="white-space:pre"> </span>sscanf(&s[1],"%d",&d); <span style="white-space:pre"> </span>addnode(d,strchr(s,',')+1); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return 0; }代码其实并没有减少多少,说简单了但是其实也有点复杂 比如left right nodes 三个数组之间的关系有时候会闹不清楚