/************************************************************************
树链式递归实现
函数:
build
getsum(获取树得节点个数)
getdep(获取树的深度 )
getlson(查找某一个节点的左子树)
getrson(查找某一个节点的右子树)
getparent(查找某一个节点的父亲)
preprint(前序遍历)
inprint(中序遍历)
postprint(后序遍历)
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int max(int x,int y)
{
if (x>y) return x;return y;
}
typedef struct binode
{
char data;
struct binode *lson,*rson;
} *bitree;
//第一种build的方法,直接在函数内部初始化T
void build(bitree *T)//*T表示传递进来的这个指针,T表示二级指针。我们进行操作的是*T。
{
char ch;
scanf("%c",&ch);
if (ch=='^')
{
(*T)=NULL;//若该位置为None,将指针置为空,否则该指针因未初始化导致指向完全随机
return;
}
*T=(bitree)malloc(sizeof(struct binode));//为指针分配空间。
//注意这里是分配指向大小为struct binode空间的指针,不是分配大小为sizeof(bitree)的空间 (bitree是一个指针)
(*T)->data=ch;
//printf("%c",(*T)->data);
bitree leftson,rightson;//新建两个指针
build(&leftson);
build(&rightson);
(*T)->lson=leftson;
(*T)->rson=rightson;//注意这里要先build再赋值
}
//第二种build的方法,传二级指针,然后通过返回bitree给T赋值
bitree build2(bitree *T)//*T表示传递进来的这个指针,T表示二级指针。我们进行操作的是*T
{
char ch;
scanf("%c",&ch);
if (ch=='^')
{
return(NULL);
}
*T=(bitree)malloc(sizeof(struct binode));//为指针分配空间,注意不是分配大小为sizeof(bitree)的空间
(*T)->data=ch;
(*T)->lson=build2(&((*T)->lson));
(*T)->rson=build2(&((*T)->rson));
return (*T);
}
//第三种build的方法,只需要传一级指针,然后通过返回bitree给T赋值。
//因为T最后是在主程序里赋值,所以我们可以先假装在build3里修改地址,然后将修改后的结果返回,最后在主程序里更新。这样更简洁
bitree build3(bitree T)//T表示传递进来的这个指针
{
char ch;
scanf("%c",&ch);
if (ch=='^')
{
return(0);
}
//printf("%p
",T);
T=(bitree)malloc(sizeof(struct binode));//为指针分配指针空间
//printf("%p
",T);
T->data=ch;
T->lson=build3(T->lson);
T->rson=build3(T->rson);
return T;
}
//get property
int getsum(bitree *T)
{
if (!(*T)) return 0;
return 1+getsum(&(*T)->lson)+getsum(&(*T)->rson);
}
int getdep(bitree *T)
{
if (!(*T)) return 0;
return 1+max(getdep(&(*T)->lson),getdep(&(*T)->rson));
}
void getparent(bitree *T,char target,char parent)
{
if (!(*T)) return;
if ((*T)->data==target)
{
printf("%c",parent);
return;
}
getparent(&(*T)->lson,target,(*T)->data);
getparent(&(*T)->rson,target,(*T)->data);
}
void getlson(bitree *T,char target)
{
if (!(*T)) return;
if ((*T)->data==target)
{
if ((*T)->lson) printf("%c",((*T)->lson)->data);
return;
}
getlson(&(*T)->lson,target);
getlson(&(*T)->rson,target);
}
void getrson(bitree *T,char target)
{
if (!(*T)) return;
if ((*T)->data==target)
{
if ((*T)->rson) printf("%c",((*T)->rson)->data);
return;
}
getrson(&(*T)->lson,target);
getrson(&(*T)->rson,target);
}
//traverse
void preprint(bitree T)
{
if (!(T)) return;
printf("%c",T->data);
preprint(T->lson);
preprint(T->rson);
}
//第二种preprint,因为不用修改指针,其实可直接传该指针,这样更为简洁。traverse和getproperty都能改写
void preprint2(bitree *T)
{
if ((*T)==NULL) return;
printf("%c",(*T)->data);
preprint2(&((*T)->lson));
preprint2(&((*T)->rson));
}
void inprint(bitree *T)
{
if (!(*T)) return;
inprint(&((*T)->lson));
printf("%c",(*T)->data);
inprint(&((*T)->rson));
}
void postprint(bitree *T)
{
if (!(*T)) return;
postprint(&((*T)->lson));
postprint(&((*T)->rson));
printf("%c",(*T)->data);
}
int main()
{
/* input: ABC^^D^^^
*
* A
* B ^
* C D
* ^^ ^^
*
*/
bitree T;//新建一个指针
build(&T);//传递这个指针的地址。如果这里写成build(T)然后在build程序直接调用T,则无法修改T的值(二级指针才能修改指针地址)
//T=build2(&T);//另外的方式
//T=build3(T);//另外的方式
printf("pre-order traverse:
");
preprint(T);
printf("
");
printf("in-oder traverse:
");
inprint(&T);
printf("
");
printf("post-order traverse:
");
postprint(&T);
printf("
");
printf("depth of tree:
");
printf("%d",getdep(&T));
printf("
");
printf("number of node:
");
printf("%d",getsum(&T));
printf("
");
printf("get parent:
");
getparent(&T,'C','^');
printf("
");
printf("get leftson:
");
getlson(&T,'A');
printf("
");
//pretest pass
}