代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int leafFormat=0;//控制二叉树叶子节点输出格式
int maxHeight=0;//计算二叉树高度
//定义二叉树结构体
typedef struct BTreeNode
{
char data[10];
struct BTreeNode* left;
struct BTreeNode* right;
} BTreeNode;

//建立二叉树
BTreeNode *CreateTree()
{
BTreeNode *t;
char x[10];
scanf("%s",x);
getchar();
if(x[0]=='0')//如果输入的为字符0,则退出
t=NULL;
else{
t=(BTreeNode*)malloc(sizeof(BTreeNode));//动态申请空间
strcpy(t->data,x);
printf("\n\t\t请输入%s结点的左子节点:",t->data);
t->left=CreateTree();
printf("\n\t\t请输入%s结点的右子节点:",t->data);
t->right=CreateTree();
}
return t;
}

//先序遍历
void PreOrder(BTreeNode *T)
{
if(!T) return ;//当前结点为空,直接退出函数

printf("%3s",T->data);//输出当前根结点
PreOrder(T->left);//递归左子树
PreOrder(T->right);//递归右子树

}

//中序遍历
void InOrder(BTreeNode *T)
{
if(!T) return ;//当前结点为空,直接退出函数

InOrder(T->left);//递归左子树
printf("%3s",T->data);//输出当前根结点
InOrder(T->right);//递归右子树

}

//后序遍历
void PostOrder(BTreeNode *T)
{
if(!T) return ;//当前结点为空,直接退出函数

PostOrder(T->left);//递归左子树
PostOrder(T->right);//递归右子树
printf("%3s",T->data);//输出当前根结点

}

//输出二叉树叶子节点
void printLeaf(BTreeNode *T){//n记录是第一个叶子节点,如果是第一个,保证输出格式
if(!T) return ;//当前结点为空,直接退出函数
if(T->left==NULL && T->right==NULL){//如果为叶子节点
if(leafFormat==0){
printf("\n\t\t叶子节点为:%s",T->data);
} else {
printf("\t%s",T->data);
}
leafFormat++;
}
printLeaf(T->left);
printLeaf(T->right);
}

//输出二叉树的叶子结点数
void Leafnum(BTreeNode *T,int *count)
{
if(!T) return ;//当前结点为空,直接退出函数
if(T->left==NULL && T->right==NULL)//且左右结点都是空,说明是叶子节点
*count=*count+1;

Leafnum(T->left,count);
Leafnum(T->right,count);

}

//输出二叉树高度
void binaryHeight(BTreeNode *T,int h){//求高度,一颗子树递归几次,高度就是多少,取最大值
if(!T) return ;//当前结点为空,直接退出函数
if(T->left==NULL && T->right==NULL){//且左右结点都是空,说明是叶子节点
maxHeight=maxHeight>h?maxHeight:h;
}
binaryHeight(T->left,h+1);
binaryHeight(T->right,h+1);
}

//打印二叉树
void printBinaryTree(BTreeNode *T,int level) { //层数
if (!T) {//如果为空节点
for (int i=0;i<level;i++) { //打印空格
printf("\t");
}
printf("NULL\n");//输出空节点
return;
}
printBinaryTree(T->right,level+1);//右结点
for (int i=0;i<level;i++) { //打印空格
printf("\t");
}
printf("%s\n",T->data);//输出当前结点
printBinaryTree(T->left,level+1);//递归左结点
}

int main()
{
BTreeNode *T=NULL;
char ch1,ch2,a;
ch1='y';
while(ch1=='y'||ch1=='y')
{
printf("\n");
printf("\n\t\t二叉树子系统");
printf("\n\t\t********************");
printf("\n\t\t* 1--建立二叉树 ");
printf("\n\t\t* 2--先序遍历 ");
printf("\n\t\t* 3--中序遍历 ");
printf("\n\t\t* 4--后序遍历 ");
printf("\n\t\t* 5--输出二叉树的叶子结点 ");
printf("\n\t\t* 6--输出叶子结点数 ");
printf("\n\t\t* 7--输出二叉树的高度 ");
printf("\n\t\t* 8--将创建的二叉树以树状形式输出 ");
printf("\n\t\t* 0--退出系统 ");
printf("\n\t\t********************");
printf("\n\t\t 请输入菜单号(0-7):");
scanf(" %c",&ch2);
printf("\n");
switch(ch2)
{
case '1':{
printf("\n\t\t请按先序序列输入二叉树的结点:\n");
printf("\n\t\t请输入根节点:");
T=CreateTree();
printf("\n\t\t二叉树成功建立\n");
break;
}
case '2':{
printf("\n\t\t该二叉树的先序遍历序列为:");
PreOrder(T);
break;
}
case '3':{
printf("\n\t\t该二叉树的中序遍历序列为:");
InOrder(T);
break;
}
case '4':{
printf("\n\t\t该二叉树的后序遍历序列为:");
PostOrder(T);
break;
}
case '5':{
leafFormat=0;
printLeaf(T);
break;
}
case '6':{
int count=0,*p=&count;
Leafnum(T,p);
printf("\n\t\t该二叉树叶子节点个数为%d",count);
break;
}
case '7':{
maxHeight=0;
binaryHeight(T,1);
printf("\n\t\t该二叉树高度为%d",maxHeight);
break;
}
case '8':{
printBinaryTree(T,0);
break;
}
case '0':{
ch1='n';break;
break;
}
default:printf("\n\t\t输入有误");
}
}
}

代码详解

前置工作

1
2
3
4
5
6
typedef struct BTreeNode
{
char data[10];
struct BTreeNode* left;
struct BTreeNode* right;
} BTreeNode;

创建结点,每个结点有一个字符数组存数据,同时还有指向左儿子和右儿子的指针

创建二叉树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BTreeNode *CreateTree()
{
BTreeNode *t;
char x[10];
scanf("%s",x);
getchar();
if(x[0]=='0')//如果输入的为字符0,则退出
t=NULL;
else{
t=(BTreeNode*)malloc(sizeof(BTreeNode));//动态申请空间
strcpy(t->data,x);
printf("\n\t\t请输入%s结点的左子节点:",t->data);
t->left=CreateTree();
printf("\n\t\t请输入%s结点的右子节点:",t->data);
t->right=CreateTree();
}
return t;
}

每次创建结点时候,如果输入0代表是NULL结点,否则便递归去创建当前结点的左儿子和右儿子,最终以先序遍历的方式去创建整颗二叉树

先序遍历

根左右遍历

1
2
3
4
5
6
7
8
9
10
//先序遍历
void PreOrder(BTreeNode *T)
{
if(!T) return ;//当前结点为空,直接退出函数

printf("%3s",T->data);//输出当前根结点
PreOrder(T->left);//递归左子树
PreOrder(T->right);//递归右子树

}

到达当前结点后,先输出当前结点的值,如果当前结点有左子树,那么就递归左子树,直到到达null结点开始回溯,然后递归右子树。

对于递归的每一个结点,都是输出当前结点,然后先递归左子树,再递归右子树

中序遍历

左根右遍历

1
2
3
4
5
6
7
8
9
10
//中序遍历
void InOrder(BTreeNode *T)
{
if(!T) return ;//当前结点为空,直接退出函数

InOrder(T->left);//递归左子树
printf("%3s",T->data);//输出当前根结点
InOrder(T->right);//递归右子树

}

到达当前结点后,先递归左子树,直到到达null结点开始回溯,输出当前结点的值,然后递归右子树。

对于递归的每一个结点,都是先递归左子树,输出当前结点的值,再递归右子树

后序遍历

左右根

1
2
3
4
5
6
7
8
9
10
//后序遍历
void PostOrder(BTreeNode *T)
{
if(!T) return ;//当前结点为空,直接退出函数

PostOrder(T->left);//递归左子树
PostOrder(T->right);//递归右子树
printf("%3s",T->data);//输出当前根结点

}

到达当前结点后,先递归左子树,直到到达null结点开始回溯,然后递归右子树,最后输出当前结点的值。

对于递归的每一个结点,都是先递归左子树,再递归右子树,最后输出当前结点的值。

输出叶子节点的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//输出二叉树叶子节点 
void printLeaf(BTreeNode *T){//n记录是第一个叶子节点,如果是第一个,保证输出格式
if(!T) return ;//当前结点为空,直接退出函数
if(T->left==NULL && T->right==NULL){//如果为叶子节点
if(leafFormat==0){
printf("\n\t\t叶子节点为:%s",T->data);
} else {
printf("\t%s",T->data);
}
leafFormat++;
}
printLeaf(T->left);
printLeaf(T->right);
}

如果到达的一个节点同时没有左子树和右子树,那么便是叶子节点,那么先序遍历的同时判断一下到达的结点是否有左子树和右子树,有的话将其输出,leafFormat是为了判断第一个输出的叶子节点,保持输出格式好看一些

输出叶子节点的个数

1
2
3
4
5
6
7
8
9
10
11
12

//输出二叉树的叶子结点数
void Leafnum(BTreeNode *T,int *count)
{
if(!T) return ;//当前结点为空,直接退出函数
if(T->left==NULL && T->right==NULL)//且左右结点都是空,说明是叶子节点
*count=*count+1;

Leafnum(T->left,count);
Leafnum(T->right,count);

}

如果到达的一个节点同时没有左子树和右子树,那么便是叶子节点

二叉树高度

1
2
3
4
5
6
7
8
9
10

//输出二叉树高度
void binaryHeight(BTreeNode *T,int h){//求高度,一颗子树递归几次,高度就是多少,取最大值
if(!T) return ;//当前结点为空,直接退出函数
if(T->left==NULL && T->right==NULL){//且左右结点都是空,说明是叶子节点
maxHeight=maxHeight>h?maxHeight:h;
}
binaryHeight(T->left,h+1);
binaryHeight(T->right,h+1);
}

判断一个节点是第多少层,是由上一层递归下来的,于是先序遍历的时候带一个层号,表示当前是第几层,递归的时候层号+1,叶子节点一定是最后一层,对所有的叶子节点的层号判个最大值就是答案。

打印二叉树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//打印二叉树
void printBinaryTree(BTreeNode *T,int level) { //层数
if (!T) {//如果为空节点
for (int i=0;i<level;i++) { //打印空格
printf("\t");
}
printf("NULL\n");//输出空节点
return;
}
printBinaryTree(T->right,level+1);//右结点
for (int i=0;i<level;i++) { //打印空格
printf("\t");
}
printf("%s\n",T->data);//输出当前结点
printBinaryTree(T->left,level+1);//递归左结点
}

竖着打印二叉树,右结点在上面,根在中间,左结点在下面,对于每个结点,先递归去右结点,如果为空便打印层号数量的空格,然后输出NULL,回溯到上一层,然后打印上一层,层数数量的空格,再输出结点值再去递归左子树