本文主要实现C语言对二叉树的构造,可存储所有类型数据,实现数据域的遍历,本文主要介绍递归的遍历方法,含详细图文;以及树高、叶子节点的计算等。
1 二叉树构造
typedef struct Tree //二叉树
{
void *data; //数据域,void* 可保存任意数据类型的地址
struct Tree *left; //左子节点指针
struct Tree *right; //右子节点指针
} Tree;
2 根据数据data创建树节点
Tree *createTreeNode(void *data) //根据数据域data创建节点
{
Tree *node = (Tree *)malloc(sizeof(Tree)); //在堆区申请内存
node->data = data;
node->left = NULL;
node->right = NULL;
}
3 前序遍历代码(详细分析部分见8.2图解)
typedef struct Student //后续以二叉树保存Student数据信息为例
{
int age;
char name[20];
} Student;
void preOrderList(Tree *root) //前序遍历,先根节点,再左(子树),再右(子树)
{
if (root == NULL)
return;
Student *stu = (Student *)root->data;
printf("{id:%d,name:%s}\t", stu->age, stu->name);
preOrderList(root->left);
preOrderList(root->right);
}
//8.2有详细图解分析过程
4 中序遍历
void inOrderList(Tree *root)
{
if (root == NULL)
return;
inOrderList(root->left);
Student *stu = (Student *)root->data;
printf("{id:%d,name:%s}\t", stu->age, stu->name);
inOrderList(root->right);
}
5 后序遍历
void postOrderList(Tree *root)
{
if (root == NULL)
return;
postOrderList(root->left);
postOrderList(root->right);
Student *stu = (Student *)root->data;
printf("{id:%d,name:%s}\t", stu->age, stu->name);
}
6 叶子节点数量计算
void countOfLeafNode(Tree *root, int *count) //统计二叉树的叶子节点,即没有左右子结点
{
if (root == NULL)
return;
if (root->left == NULL && root->right == NULL)//叶子节点即没有后驱节点
(*count)++;
countOfLeafNode(root->left, count);//结合前序遍历计算叶子节点数量
countOfLeafNode(root->right, count);
}
7 树高计算
size_t heightOfTree(Tree *root)//函数的分析过程,可结果8.2图解对前序遍历的分析
{
if (root == NULL)
return 0;
int heightOfLeftTree = heightOfTree(root->left);
int heightOfRightTree = heightOfTree(root->right);
int heightOfTree = heightOfLeftTree > heightOfRightTree ? heightOfLeftTree + 1 : heightOfRightTree + 1;//得到左子树和右子树的高度最大值,再加一,即树高
return heightOfTree;
}
8 函数测试与结果分析
#include
#include
#include
int main()
{
Student stu[7] = {
{1, "jakes1"},
{2, "jakes2"},
{3, "jakes3"},
{4, "jakes4"},
{5, "jakes5"},
{6, "jakes6"},
{7, "jakes7"},
};
Tree *root = (Tree *)malloc(sizeof(Tree));
root->data = &stu[0];
root->left = createTreeNode(&stu[1]);
root->right = createTreeNode(&stu[2]);
root->left->left = createTreeNode(&stu[3]);
root->left->left->right = createTreeNode(&stu[6]);
root->right->left = createTreeNode(&stu[4]);
root->right->right = createTreeNode(&stu[5]);
printf("前序遍历:");
preOrderList(root);
printf("\n中序遍历:");
inOrderList(root);
printf("\n后序遍历:");
postOrderList(root);
puts("");
int count = 0;
countOfLeafNode(root, &count);//count入参传址
printf("叶子节点数量为:%d\n", count);
printf("树的高度为%d\n", heightOfTree(root));
return 0;
}
8.1 main函数中,对树的构建如下图
8.2 以前序遍历为例,程序的执行顺序可参考下图。preOrderList()函数入参为Tree *类型,为简单绘图,简化为stu0、stu1.....,图中有4个printf(NULL),应该是pre(NULL),图画得略微仓促,但有助于对递归排序的理解。
8.3 中序遍历和后续遍历均可按照此方法分析,main函数的运行结果如下:
9 补充一些关于树的基本概念
9.1 根:没有前驱
9.2 叶子:没有后继
9.3 双亲:直接前驱
9.4 孩子:直接后继
9.5 节点的度:直接后继的数量
9.6 树的度:节点的度中取最大值
9.7 树的高度/深度:最大层数
9.8 二叉树:
9.8.1 在二叉树的第i层上最多2^(i-1)个节点
9.8.2 深度为k的二叉树至多有2^k-1个节点,若有2^k-1个节点,则成为满二叉树;
若仅在最后一层缺少右边的若干节点,其他层节点数已达到最大,成为完全二叉树,
满二叉树肯定是完全二叉树
9.8.3 若度为2的节点数有n个,则叶子数必定为n+1;(叶子是指没有后继)
9.8.4 具有n个节点的完全二叉树的深度必为int((log2)n)+1
9.8.5对于完全二叉树,若从左至右,从上到下,对节点编号,节点i的左子节点必为2i
右子节点必为2i+1,父节点必为(int)i/2
点击关注不迷路