目录
1. 二叉树定义
在堆(C语言)章节我们已经了解了堆的数据结构是完全二叉树。而二叉树的定义则更加广泛,限制也比完全二叉树少:
- 空树(节点数为0)
- 每个节点的子节点数不超过两个
例如以下这些都是二叉树:

2. 代码实现
// 二叉树的创建会放在之后的章节进行说明,这里先临时用古法建树 >"<
代码主要采用递归的方式实现各函数功能,文件内部有详细注释:
//BinaryTree.h文件
#pragma once
#include<stdlib.h>
#include<math.h>
#include<stdio.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType val;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
//新建树节点
BTNode* BuyNode(BTDataType val);
//创建固定二叉树,返回根节点
BTNode* CreateBinaryTree();
//前序遍历
void PreOrder(BTNode* root);
//中序遍历
void MidOrder(BTNode* root);
//后序遍历
void PostOrder(BTNode* root);
//计算节点个数
int TreeSize(BTNode* root);
//计算叶子节点数
int LeafSize(BTNode* root);
//计算树的高度
int TreeHeight(BTNode* root);
//计算第K层节点个数
int LeafLevelKSize(BTNode* root, int k);
//根据值查找节点
BTNode* TreeFind(BTNode* root, BTDataType x);
//BinaryTree.c文件
#include "BinaryTreeNode.h"
//新建树节点
BTNode* BuyNode(BTDataType val)
{
BTNode* tmp = (BTNode*)malloc(sizeof(BTNode));
if(tmp == NULL)
{
perror("malloc fail");
exit(1);
}
tmp->val = val;
tmp->left = NULL;
tmp->right = NULL;
return tmp;
}
//创建固定二叉树
BTNode* CreateBinaryTree()
{
BTNode* node1 = BuyNode(1);
BTNode* node2 = BuyNode(2);
BTNode* node3 = BuyNode(3);
BTNode* node4 = BuyNode(4);
BTNode* node5 = BuyNode(5);
BTNode* node6 = BuyNode(6);
node1->left = node2;
node1->right = node4;
node2->left = node3;
node4->left = node5;
node4->right = node6;
return node1;
}
//前序遍历
void PreOrder(BTNode* root)
{
if(!root)
return;
printf("%d ", root->val); //根
PreOrder(root->left); //左
PreOrder(root->right); //右
}
//中序遍历
void MidOrder(BTNode* root)
{
if(!root)
return;
MidOrder(root->left); //左
printf("%d ", root->val); //根
MidOrder(root->right); //右
}
//后序遍历
void PostOrder(BTNode* root)
{
if(!root)
return;
PostOrder(root->left); //左
PostOrder(root->right); //右
printf("%d ", root->val); //根
}
//计算节点个数
int TreeSize(BTNode* root)
{
if(!root)
return 0;
//左子树节点数 + 右子树节点数 + 当前节点
return TreeSize(root->left) + TreeSize(root->right) + 1;
}
//计算叶子节点数
int LeafSize(BTNode* root)
{
//要考虑root为空的情况!否则会报错
if(!root)
return 0;
//左右都为空,即为叶子节点
if(!root->left && !root->right)
return 1;
return LeafSize(root->left) + LeafSize(root->right);
}
//计算树的高度
int TreeHeight(BTNode* root)
{
if(!root)
return 0;
//取左右子树中较深的一棵,算入当前层数
return fmax(TreeHeight(root->left), TreeHeight(root->right)) + 1;
}
//计算第K层节点个数
int LeafLevelKSize(BTNode* root, int k)
{
if(!root)
return 0;
//到达K层则将当前节点计入总数
if(k == 1)
return 1;
return LeafLevelKSize(root->left, k-1) + LeafLevelKSize(root->right, k-1);
}
//根据值查找节点
BTNode* TreeFind(BTNode* root, BTDataType x)
{
if(!root)
return NULL;
if(root->val == x)
return root;
BTNode* ret1 = TreeFind(root->left, x);
if(ret1 != NULL)
{
return ret1; //找到就return,不必遍历右子树
}
BTNode* ret2 = TreeFind(root->right, x);
if(ret2 != NULL)
{
return ret2;
}
return NULL; //注意不要漏掉if条件之外的return!
}
这里附上一个测试文件:
#include "BinaryTreeNode.h"
#include "BinaryTreeNode.c"
int main()
{
BTNode* root = CreateBinaryTree();
PreOrder(root);
printf("\n");
MidOrder(root);
printf("\n");
PostOrder(root);
printf("\n");
int size = TreeSize(root);
printf("树的节点个数为%d个。\n", size);
int leaf = LeafSize(root);
printf("树的叶子节点个数为%d个。\n", leaf);
int height = TreeHeight(root);
printf("树的高度为%d。\n", height);
int k = 0;
printf("树的高度为%d,请输入你要查询的层数:\n", height);
scanf("%d", &k);
int LevelKNode = LeafLevelKSize(root, k);
printf("第%d层的节点数为%d。\n", k, LevelKNode);
int FindVal = 0;
printf("请输入你要查找的值:\n");
scanf("%d", &FindVal);
BTNode* FindOut = TreeFind(root, FindVal);
if(!FindOut)
{
printf("没有找到。\n");
}
else
{
printf("找到了。\n");
}
return 0;
}
3. 补充代码
在以上代码的基础上新增了:
- 二叉树的销毁
- 层序遍历
- 判断是否为二叉树
- 根据前序遍历创建二叉树(其中符号#为NULL)
其中第4点是基于一道类似的牛客题实现的:
// BinaryTreeNode.h文件
//销毁二叉树
void TreeDestroy(BTNode* root);
//层序遍历
void TreeLevelOrder(BTNode* root);
//判断是否为完全二叉树
bool isBinaryTree(BTNode* root);
//根据前序遍历创建二叉树
//D:\CODE\STUDY\BYTE CLASS\NC_TSINGK110.c
BTNode* PrevCreateBinaryTree(char* a, int* pi);
// BinaryTreeNode.c文件
//销毁二叉树
void TreeDestroy(BTNode* root)
{
if(!root) return;
TreeDestroy(root->left);
TreeDestroy(root->right);
free(root);
//根据后续遍历的方式销毁,避免找不到后续节点
}
//层序遍历(非递归)
void TreeLevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if(root)
{
QueuePush(&q, root);
}
while(!QueueEmpty(&q))
{
BTNode* top = QueueFront(&q);
QueuePop(&q);
printf("%d ", top->val);
if(top->left) QueuePush(&q, top->left);
if(top->right) QueuePush(&q, top->right);
}
printf("\n");
QueueDestroy(&q);
}
//判断是否为完全二叉树(把NULL节点也放入队列中)
bool isBinaryTree(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while(!QueueEmpty(&q))
{
BTNode* top = QueueFront(&q);
QueuePop(&q);
if(top == NULL)
{
break;
}
QueuePush(&q, top->left);
QueuePush(&q, top->right);
}
while(!QueueEmpty(&q))
{
BTNode* top = QueueFront(&q);
QueuePop(&q);
if(top)
{
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}
//根据前序遍历创建二叉树(i为字符数组a的下标,从0开始,传址确保实参改变)
BTNode* PrevCreateBinaryTree(char* a, int* pi)
{
if(a[*pi] == '#')
{
(*pi)++; //记得加括号!不要写在if里面!因为只要判断就会+1
return NULL;
}
BTNode* root = (BTNode*)malloc(sizeof(BTNode));
if(!root)
{
perror("malloc fail");
exit(1);
}
//初始化
root->val = a[(*pi)++] - '0'; //转化为整型数据存入
root->left = PrevCreateBinaryTree(a, pi);
root->right = PrevCreateBinaryTree(a, pi);
return root;
}
// 感谢阅读~( ̄︶ ̄)↗
&spm=1001.2101.3001.5002&articleId=159929868&d=1&t=3&u=ece0c83b14764af68640f8fe29769502)
2万+

被折叠的 条评论
为什么被折叠?



