数据结构:二叉树中的叶子结点和非叶子结点的求法。
前言
叶子结点: 没有左孩子和右孩子,指向NULL, 非叶子结点:根结点和有左孩子或者右孩子,可能全有的情况,这是咱们递归遍历的结束的条件。
提示:以下是本篇文章正文内容,下面案例可供参考
一、叶子和非叶子结点区别
叶子结点数是在结点无左孩子和无右孩子的情况+1,不和递归同时进行,而非叶子结点则是+1,和递归同时进行。 原因:叶子结点是使递归结束的条件,和递归进行是相反的,故不能放在一起。
二、求法和打印
1.叶子结点数求法
代码如下(示例):
//求叶子结点函数
int leaf_node_function(RTreeNode *p)
{
if(!p)
{
return 0; //空二叉树的情况
}
else if(p->left_child == NULL && p->right_child == NULL)
{
return + 1;
}
else
{
return leaf_node_function(p->left_child) + leaf_node_function(p->right_child);
}
} //因为我们用的递归是根结点开始的,所以必须把递归的函数放在else(非叶子结点这里)
//打印叶子结点
void leaf_print(RTreeNode *p)
{
if(p != NULL)
{
if(p->left_child == NULL && p->right_child == NULL)
{
printf("%c ", p->data);
}
leaf_print(p->left_child);
leaf_print(p->right_child);
}
}
2.非叶子结点数求法
代码如下(示例):
//求非叶子结点函数
int Non_leaf_node_function(RTreeNode *p)
{
if(!p)
{
return 0; //空二叉树
}
else if(p->left_child == NULL && p->right_child == NULL)
{
return 0; //结点为叶子结点 = 左子树 + 右子树 = NULL
}
else
{
return Non_leaf_node_function(p->left_child) + Non_leaf_node_function(p->right_child) + 1;
}//就利用控制流程语句,就能控制递归
}
//打印非叶子结点
void Non_leaf_print(RTreeNode *p)
{
if(p != NULL)
{
if(!(p->left_child == NULL && p->right_child == NULL)) //为叶子结点的
{
printf("%c ", p->data);
}
Non_leaf_print(p->left_child);
Non_leaf_print(p->right_child);
}
}
三,代码实现
//
// Created by xoo on 2021/7/7.
//
//采用静态建立二叉树,求叶子结点和非叶子结点
#include<stdio.h>
#include<stdlib.h>
typedef struct TreeNode
{
struct TreeNode *left_child, *right_child;
char data;
}RTreeNode;
//生成一个结点
RTreeNode *init_node(char x, RTreeNode *left_child, RTreeNode *right_child)
{
RTreeNode *node;
node = (struct TreeNode*) malloc(sizeof(struct TreeNode));
node->left_child = left_child;
node->right_child = right_child;
node->data = x;
return node;
}
//生成一颗二叉树树
RTreeNode *create_tree()
{
RTreeNode *root, *b, *c, *d, *e, *f;
d = init_node('D', NULL, NULL);
e = init_node('E', NULL, NULL);
f = init_node('F', NULL, NULL);
b = init_node('B', d, NULL);
c = init_node('C', e, f);
root = init_node('A', b, c);
return root;
}
//求叶子结点函数
int leaf_node_function(RTreeNode *p)
{
if(!p)
{
return 0; //空二叉树的情况
}
else if(p->left_child == NULL && p->right_child == NULL)
{
return + 1;
}
else
{
return leaf_node_function(p->left_child) + leaf_node_function(p->right_child);
}
} //因为我们用的递归是根结点开始的,所以必须把递归的函数放在else(非叶子结点这里)
//求非叶子结点函数
int Non_leaf_node_function(RTreeNode *p)
{
if(!p)
{
return 0; //空二叉树
}
else if(p->left_child == NULL && p->right_child == NULL)
{
return 0; //结点为叶子结点 = 左子树 + 右子树 = NULL
}
else
{
return Non_leaf_node_function(p->left_child) + Non_leaf_node_function(p->right_child) + 1;
}
}
//打印非叶子结点
void Non_leaf_print(RTreeNode *p)
{
if(p != NULL)
{
if(!(p->left_child == NULL && p->right_child == NULL)) //为叶子结点的
{
printf("%c ", p->data);
}
Non_leaf_print(p->left_child);
Non_leaf_print(p->right_child);
}
}
//打印叶子结点
void leaf_print(RTreeNode *p)
{
if(p != NULL)
{
if(p->left_child == NULL && p->right_child == NULL)
{
printf("%c ", p->data);
}
leaf_print(p->left_child);
leaf_print(p->right_child);
}
}
//前序遍历
void preorder(RTreeNode *p)
{
if(p != NULL)
{
printf("->%c", p->data);
preorder(p->left_child);
preorder(p->right_child);
}
}
int main()
{
RTreeNode *root;
root = create_tree();
printf("前序遍历:");
preorder(root);
printf("\n");
printf("非叶子的个数:%d", Non_leaf_node_function(root));
printf("\n");
printf("非叶子结点:");
Non_leaf_print(root);
printf("\n");
printf("求叶子结点的个数:%d", leaf_node_function(root));
printf("\n叶子结点:");
leaf_print(root);
printf("\n");
system("pause");
return 0;
}
结果:
总结
其实和二叉树的动态建立有很大关联, 只需要理解如何用递归建立起二叉树,求叶子和非叶子结点就很简单,因为你理解了它的递归思路,很容易想到该如何控制递归结束条件。