///*题目:树的基本运算
///*作者:仲舟
///*难度:★★★
///*完成时间:2021.04.27
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define m 3
#define MAXLEN 100
typedef char datatype;
typedef struct node {
datatype data;
struct node *child[m];
} node;
typedef node *tree;
tree CreateTree(); /*按前序遍历顺序建立一棵3度树,返回树根地址 */
void LevelOrder(tree t); /* t为指向树根结点的指针,输出树的层次遍历序列*/
void PreOrder(tree t); /* t为指向树根结点的指针,输出树的前序遍历序列*/
void PostOrder(tree t); /* t为指向树根结点的指针,输出树的后序遍历序列*/
int main() {
tree t;
t=CreateTree();
printf("\nthe LevelOrder is:");
LevelOrder(t);
printf("\nthe PreOrder is:");
PreOrder(t);
printf("\nthe PostOrder is:");
PostOrder(t);
return 0;
}
tree CreateTree() {
int i;
char ch;
tree t;
if ((ch=getchar())=='#') t=NULL;
else {
t=(tree) malloc (sizeof(node));
t->data=ch;
for (i=0; i<m; ++i)
t->child[i]= CreateTree();
}
return t;
}
void LevelOrder(tree t) { /* t为指向树根结点的指针,输出树的层次遍历序列*/
/*仲舟猜测:层次遍历是访问一层中的所有结点,而递归是不断访问子结点,所以用递归无法实现层次遍历,层级访问只需用循环即可*/
/*层次遍历可以理解为:树由高到低,高层的比低层的年纪大,左层比右层年纪大,只要按年纪大小从大到小排列输出就说层次排列,
为了更好理解,下面做个《细胞分裂》游戏,队列用“按年龄从大到小排列的活细胞”表示,每个细胞的寿命都一样,当他死后即细胞分裂,会分裂出新生细胞*/
tree queue[MAXLEN],die;//队列(用于按年龄从大到小排列),将要死亡的细胞
int l,r;//队列最左下标、队列最右下标
r=l=0;//初始化
queue[r++]=t;//原生细胞入队
while(l<r)//队列还有就执行
{
die=queue[l++];//最左边的那个细胞将要死了
printf("%c",die->data);//先把它刻在墓碑上(输出)
for(int i=0;i<=m-1;i++)//再计算它分了几个细胞
if(die->child[i]!=NULL)//如果分裂了
queue[r++]=die->child[i];//它的孩子入队
}
}
void PreOrder(tree t) /* t为指向树根结点的指针,输出树的前序遍历序列*/
{
if(t->data!='#') { //如果不为空
printf("%c",t->data);//先输出老子
for(int i=0; i<=m-1; i++) //再找孩子
if(t->child[i])//如果有孩子
PreOrder(t->child[i]);
}
//如果空,则终止递归
}
void PostOrder(tree t) /* t为指向树根结点的指针,输出树的后序遍历序列*/
{
if(t->data!='#') { //如果不为空
for(int i=0; i<=m-1; i++) //先找孩子
if(t->child[i])
PostOrder(t->child[i]);
printf("%c",t->data);//再输出老子
}
//如果空,则终止递归
}
///*题目:求树中叶子结点的个数以及树t中结点值为x的结点的层号
///*作者:仲舟
///*难度:★★
///*完成时间:2021.04.27
#include <stdlib.h>
#include <malloc.h>
#define m 3
#define MAXLEN 20
typedef char datatype;
typedef struct node {
datatype data;
struct node *child[m];
} node;
typedef node *tree;
tree CreateTree(); /*按前序遍历顺序建立一棵3度树,返回树根地址 */
int LeafNodes(tree t); /* 求树t中叶子结点的个数,返回值为叶子结点个数*/
int Level(tree t,datatype x,int h);
/* 求树t中结点值为x的结点的层号,h为辅助参数,记录树t的层号,
返回值为结点值为x的结点层号,假设根结点的层号为1。
若树t中不存在结点值为x的结点,返回0*/
int main()
{
int N,level;
datatype ch;
tree t;
t=CreateTree();
printf("\nthe LeafNodes is:%d\n",LeafNodes(t));
scanf("%d",&N);getchar();
while(N--){
scanf("%c",&ch);getchar();
level=Level(t,ch,1);
if (level==0) printf("the node %c is not exist.\n",ch);
else printf("the level of the node %c is %d\n",ch,level);
}
return 0;
}
tree CreateTree()
{
int i;
char ch;
tree t;
if ((ch=getchar())=='#') t=NULL;
else{
t=(tree) malloc (sizeof(node));
t->data=ch;
for (i=0;i<m;++i)
t->child[i]= CreateTree();
}
return t;
}
/*仲舟提示:用递归思想:假设我这个LeafNodes(t)函数能用,它返回值的应该是下一个孩子树它所带有的结点,我要把这个值返回给它父亲,应该是return LeafNodes(t孩子),这是我一层该做的事,如果每个函数都像我一样,那么就可以完成整个任务*/
int LeafNodes(tree t) /* 求树t中叶子结点的个数,返回值为叶子结点个数*/
{
if(t)//如果t存在
{
if(!t->child[0]&&!t->child[1]&&!t->child[2])//并且它的孩子都没有,即它是叶结点
return 1;//终止递归,返回1,表示找到了一个结点
else//如果有孩子
return LeafNodes(t->child[0])+LeafNodes(t->child[1])+LeafNodes(t->child[2]);//要返回把三个孩子的树的叶结点加起来,继续递归
}
else//如果t不存在
return 0;
}
int Level(tree t,datatype x,int h)
/* 求树t中结点值为x的结点的层号,h为辅助参数,记录树t的层号,
返回值为结点值为x的结点层号,假设根结点的层号为1。
若树t中不存在结点值为x的结点,返回0*/
{
if(t)//如果t存在
{
if(t->data==x)//如果找到
return h;//返回层数
else//如果没找到
return Level(t->child[0],x,h+1)+Level(t->child[1],x,h+1)+Level(t->child[2],x,h+1);//再找三个孩子有没有,层数+1
}
else//如果t不存在
return 0;
}
仲舟原创,未经允许禁止转载!