- 求二叉树叶子结点个数。
- 求二叉树的宽度。
- 求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值。
- 输出二叉树中从每个叶子结点到根结点的路径。
目录
//树的结构定义
//二叉树:
typedef struct BTree {
elemtype data;
struct BTree* left;
struct BTree* right;
}*BTree
//求叶子结点个数
思路:在遍历的基础上加一个判断语句和一个计数器,判断该节点是不是叶子节点,是的话计数器就加1.
//求叶子结点数
//前序遍历的方式
int count = 0; //计数器
void GetNum(BTree root) {
if (root == NULL)
return;
if (root->left == NULL && root->right == NULL) {//叶子结点
++count;
return;
}
GetNum(root->left);
GetNum(root->right);
}
//求树的宽度
思路:用层次遍历的方式,比较每一层的结点数,最大的就是整颗树的宽度。先定义一个新的结构体,用来描述每一个结点所在的层次数,再定义一个队列,给所有的结点都记录上自己的层数,最后比较。
//用一个新结构体记录每一个结点所在的层数
typedef struct Width {
BTree p; //树的结点
int num; //该节点层数
}Width;
//求树的宽度
int GetWidth(BTree root) {
BTree p = root;
Width Queue[MAXSIZE]; //建一个队列
int front = 0; //队首指针
int rear = 0; //队尾指针
int num = 1; //初始层数
BTree q = NULL; //辅助结点
if (p != NULL) {
Queue[rear].p = p; //结点入队
Queue[rear++].num = num; //该结点所在层数
//先确定每一个结点所在的层数
while (rear != front) { //队不为空
q = Queue[front].p; //出队
num = Queue[front++].num; //获得当前结点的所在层数
if (q->left) { //左儿子存在就把左儿子入队
Queue[rear].p = q->left; //入队
Queue[rear++].num = num + 1; //所在层次要加1
}
if (q->right) {
Queue[rear].p = q->right;
Queue[rear++].num = num + 1;
}
}
int i = 0; //i作队列指针
int max = 0; //宽度
num = 1; //重置层次数
while (i < rear) {
int count = 0; //计数器,每层节点数
while (i < rear && Queue[i].num == num) { //统计同一层上结点数
++count;
++i;
}
num++; //层次加1
if (max < count)
max = count;
}
return max;
}
return 0;
}
//求树的深度
思路:采用递归的方法,分别算出左子树和右子树的深度,然后比较两边深度大小,大的作为整颗树的深度。
//求树的深度
//递归方法
int Depth(BTree root) {
if (root == NULL)
return 0;
int ldpeth = Depth(root->left) + 1; //左子树深度
int rdpeth = Depth(root->right) + 1;//右子树深度
return ldpeth > rdpeth ? ldpeth : rdpeth; //返回最深的子树的深度
}
//求最长路径
思路:还是用递归,中间通过判断两边的深度来决定递归的子树。
//求最长路径
void Long(BTree root) {
if (root == NULL)
return;
printf("%c ", root->data);
if (Depth(root->left) > Depth(root->right)) //判断哪边的深度最深
Long(root->left);
else
Long(root->right);
}
//求叶子节点到根节点的路径
思路:用辅助栈来操作,将叶子结点前的每一个结点值存入栈中,如果遇到叶子结点,就打印栈中的结点值,这就是根结点到该叶子结点的路径。
//叶子到根的路径
//辅助栈:
typedef struct Stack {
int top;//栈顶指针
elemtype data[MAXSIZE];
}*Stack;
Stack stack;
//栈的初始化:
void init() {
stack = (Stack)malloc(sizeof(struct Stack));
stack->top = -1;
}
//压栈操作
void Push(elemtype ch) {
stack->data[++stack->top] = ch;
}
//出栈操作
void Pop() {
stack->top--;
}
//打印栈
void PrintStack() {
printf("%c", stack->data[0]);
for (int i = 1; i <= stack->top; i++) {
printf("-->%c", stack->data[i]);
}
printf("\n");
}
//求路径
void Path(BTree root) {
if (root) {
Push(root->data); //先将结点值压栈
if (!root->left && !root->right) { //如果这个结点是叶子就打印栈里的内容
PrintStack();
}
else { //不是的话就递归左子树和右子树
Path(root->left);
Path(root->right);
}
Pop(); //出栈,改变叶子结点,改变路径的终点
}
}
//加主函数的完整测试源码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
#define elemtype char
#define MAXSIZE 15
//二叉树:
typedef struct BTree {
elemtype data;
struct BTree* left;
struct BTree* right;
}*BTree;
void menu() {
printf("================\n");
printf("1、求叶子结点数\n");
printf("2、求二叉树宽度\n");
printf("3、最长路径长度\n");
printf("4、叶子到根路径\n");
printf("5、二叉树的深度\n");
printf("================\n");
}
//队列初始化树
BTree InitTree(BTree root) {
BTree Queue[MAXSIZE + 1]; //创建队,+1防止溢出
int front = 1; //队首指针,从1开始方便后面的左右儿子判断
int rear = 0; //队尾指针。从0开始方便后面计算
BTree new; //新节点
elemtype ch; //结点值
while ((ch = getchar()) != '\n') {
new = (BTree)malloc(sizeof(struct BTree));
new->data = ch;
new->left = new->right = NULL;
Queue[++rear] = new; //入队
if (root == NULL)
root = new;
if (Queue[rear]->data == '#')
Queue[rear] = NULL;
if (rear == front * 2) //判断是否是root的左儿子
Queue[front]->left = Queue[rear];
if (rear == front * 2 + 1) { //判断是否是root的右儿子
Queue[front]->right = Queue[rear];
front++; //如果是右儿子那代表着这个结点已经操作完了,就将front加1(出队)
}
}
return root;
}
//求叶子结点数
//前序遍历的方式
int count = 0; //计数器
void GetNum(BTree root) {
if (root == NULL)
return;
if (root->left == NULL && root->right == NULL) {
++count;
return;
}
GetNum(root->left);
GetNum(root->right);
}
//求树的宽度
//用一个结构体记录每一个结点所在的层数
typedef struct Width {
BTree p; //树的结点
int num; //该节点层数
}Width;
int GetWidth(BTree root) {
BTree p = root;
Width Queue[MAXSIZE]; //建一个队列
int front = 0; //队首指针
int rear = 0; //队尾指针
int num = 1; //初始层数
BTree q = NULL; //辅助结点
if (p != NULL) {
Queue[rear].p = p; //结点入队
Queue[rear++].num = num; //该结点所在层数
//先确定每一个结点所在的层数
while (rear != front) { //队不为空
q = Queue[front].p; //出队
num = Queue[front++].num; //获得当前结点的所在层数
if (q->left) { //左儿子存在就把左儿子入队
Queue[rear].p = q->left; //入队
Queue[rear++].num = num + 1; //所在层次要加1
}
if (q->right) {
Queue[rear].p = q->right;
Queue[rear++].num = num + 1;
}
}
int i = 0; //i作队列指针
int max = 0; //宽度
num = 1; //重置层次数
while (i < rear) {
int count = 0; //计数器,每层节点数
while (i < rear && Queue[i].num == num) { //统计同一层上结点数
++count;
++i;
}
num++; //层次加1
if (max < count)
max = count;
}
return max;
}
return 0;
}
//求树的深度
//递归方法
int Depth(BTree root) {
if (root == NULL)
return 0;
int ldpeth = Depth(root->left) + 1; //左子树深度
int rdpeth = Depth(root->right) + 1;//右子树深度
return ldpeth > rdpeth ? ldpeth : rdpeth; //返回最深的子树的深度
}
//求最长路径
void Long(BTree root) {
if (root == NULL)
return;
printf("%c ", root->data);
if (Depth(root->left) > Depth(root->right)) //判断哪边的深度最深
Long(root->left);
else
Long(root->right);
}
//叶子到根的路径
//辅助栈:
typedef struct Stack {
int top;//栈顶指针
elemtype data[MAXSIZE];
}*Stack;
Stack stack;
//栈的初始化:
void init() {
stack = (Stack)malloc(sizeof(struct Stack));
stack->top = -1;
}
//压栈操作
void Push(elemtype ch) {
stack->data[++stack->top] = ch;
}
//出栈操作
void Pop() {
stack->top--;
}
//打印栈
void PrintStack() {
printf("%c", stack->data[0]);
for (int i = 1; i <= stack->top; i++) {
printf("-->%c", stack->data[i]);
}
printf("\n");
}
//求路径
void Path(BTree root) {
if (root) {
Push(root->data); //先将结点值压栈
if (!root->left && !root->right) { //如果这个结点是叶子就打印栈里的内容
PrintStack();
}
else { //不是的话就递归左子树和右子树
Path(root->left);
Path(root->right);
}
Pop(); //出栈,改变叶子结点,改变路径的终点
}
}
int main(){
init();
int chose = 0;
BTree root=NULL;
printf("用对列初始化,‘#’代表虚结点:\n");
root=InitTree(root); //初始化树
while (1) {
menu();
scanf("%d", &chose);
switch (chose) {
case 1: //叶子节点数目
GetNum(root);
printf("叶子结点数是:%d\n",count);
count = 0;
break;
case 2://树的最大宽度
printf("宽度是%d\n", GetWidth(root));
break;
case 3://树的最长路径
Long(root);
printf("\n");
break;
case 4://树的所有路径
Path(root);
break;
case 5://树的深度
printf("二叉树的深度是:%d\n", Depth(root));
break;
default:return;
}
}
return 0;
}