本文将介绍如何使用 C 语言实现二叉树的基本操作,包括创建、遍历、统计节点、查找、判断完全二叉树等。代码结构清晰,适合初学者学习和扩展。
📁 项目结构
我们使用三个文件来组织代码:
-
tree.h:声明二叉树结构和相关函数 -
tree.c:实现二叉树的各项功能 -
test.c:测试代码,验证功能是否正确
📘 头文件定义(tree.h)
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
typedef char BTDataType;
typedef struct BinaryTreeNode {
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
} BTNode;
// 函数声明
BTNode* BinaryTreeCreate(BTDataType* a, int* pi);
void BinaryTreeDestory(BTNode* root);
int BinaryTreeSize(BTNode* root);
int BinaryTreeLeafSize(BTNode* root);
int BinaryTreeLevelKSize(BTNode* root, int k);
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
void BinaryTreePrevOrder(BTNode* root);
void BinaryTreeInOrder(BTNode* root);
void BinaryTreePostOrder(BTNode* root);
void BinaryTreeLevelOrder(BTNode* root);
int BinaryTreeComplete(BTNode* root);
int BinaryTreeDepth(BTNode* root);
🔧 功能实现(tree.c)
1. 创建二叉树
使用前序遍历序列(如 "AB#C##DE##F##")构建二叉树,# 表示空节点。
BTNode* BinaryTreeCreate(BTDataType* a, int* pi) {
assert(a);
if (a[*pi] == '#') {
(*pi)++;
return NULL;
}
BTNode* root = (BTNode*)malloc(sizeof(BTNode));
if (root == NULL) {
perror("malloc error");
exit(1);
}
root->_data = a[*pi];
(*pi)++;
root->_left = BinaryTreeCreate(a, pi);
root->_right = BinaryTreeCreate(a, pi);
return root;
}
2. 销毁二叉树
递归释放所有节点内存:
void BinaryTreeDestory(BTNode* root) {
if (root == NULL) return;
BinaryTreeDestory(root->_left);
BinaryTreeDestory(root->_right);
free(root);
}
3. 统计节点个数
int BinaryTreeSize(BTNode* root) {
if (root == NULL) return 0;
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}
4. 计算二叉树深度
int BinaryTreeDepth(BTNode* root) {
if (root == NULL) {
return 0;
}
int left = BinaryTreeDepth(root->_left) + 1;
int right = BinaryTreeDepth(root->_right) + 1;
return left >= right ? left : right;
}
5. 计算第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k) {
assert(k > 0);
if (root == NULL) {
return 0;
}
if (k == 1) {
return 1;
}
k--;
return BinaryTreeLevelKSize(root->_left, k) + BinaryTreeLevelKSize(root->_right, k);
}
6. 查找节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x) {
if (root == NULL) return NULL;
if (root->_data == x) return root;
BTNode* left = BinaryTreeFind(root->_left, x);
if (left) return left;
return BinaryTreeFind(root->_right, x);
}
7. 三种递归遍历(前序、中序、后序)
// 前序遍历:根 -> 左 -> 右
void BinaryTreePrevOrder(BTNode* root) {
if (root == NULL) return;
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left);
BinaryTreePrevOrder(root->_right);
}
// 中序遍历:左 -> 根 -> 右
void BinaryTreeInOrder(BTNode* root) {
if (root == NULL) return;
BinaryTreeInOrder(root->_left);
printf("%c ", root->_data);
BinaryTreeInOrder(root->_right);
}
// 后序遍历:左 -> 右 -> 根
void BinaryTreePostOrder(BTNode* root) {
if (root == NULL) return;
BinaryTreePostOrder(root->_left);
BinaryTreePostOrder(root->_right);
printf("%c ", root->_data);
}
8. 层序遍历(使用队列)(基于先前博客实现的队列)
需配合一个队列实现:
void BinaryTreeLevelOrder(BTNode* root) {
if (root == NULL) return;
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q)) {
BTNode* head = QueueFront(&q);
printf("%c ", head->_data);
if (head->_left) QueuePush(&q, head->_left);
if (head->_right) QueuePush(&q, head->_right);
QueuePop(&q);
}
QueueDestroy(&q);
}
9. 计算叶子节点个数
int BinaryTreeLeafSize(BTNode* root) {
if (root == NULL) {
return 0;
}
if (root->_left == NULL && root->_right == NULL) {
return 1;
}
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
10. 判断是否是完全二叉树
int BinaryTreeComplete(BTNode* root) {
if (root == NULL) return 1;
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q)) {
BTNode* head = QueueFront(&q);
if (head == NULL) break;
QueuePush(&q, head->_left);
QueuePush(&q, head->_right);
QueuePop(&q);
}
while (!QueueEmpty(&q)) {
if (QueueFront(&q) != NULL) return 0;
QueuePop(&q);
}
return 1;
}
🧪 测试代码(test.c)
#include "tree.h"
void TestBinaryTree(BTNode* root) {
char a[] = "AB#C##DE##F##";
int i = 0;
//测试创建树
root = BinaryTreeCreate(a, &i);
//测试计算结点个数
printf("该二叉树的结点个数为:%d\n", BinaryTreeSize(root));
//测试二叉树的深度
printf("该二叉树的深度为:%d\n", BinaryTreeDepth(root));
//测试二叉树第k层节点个数
printf("请输入要查询第几层结点的个数:");
int k = 0;
scanf("%d", &k);
if (k <= BinaryTreeDepth(root))
printf("第%d层的结点个数为:%d\n", k, BinaryTreeLevelKSize(root, k));
else printf("超出树的最大深度\n");
//测试二叉树查找值为x的节点
char c;
while ((c = getchar()) != '\n' && c != EOF);
BTDataType x;
printf("请输入要查找的结点的值:");
scanf("%c", &x);
BTNode* node = BinaryTreeFind(root, x);
if (node) {
printf("%c\n", node->_data);
} else {
printf("不存在该结点\n");
}
//测试前中后序遍历
printf("前序遍历:");
BinaryTreePrevOrder(root);
printf("\n");
printf("中序遍历:");
BinaryTreeInOrder(root);
printf("\n");
printf("后序遍历:");
BinaryTreePostOrder(root);
printf("\n");
//测试层序遍历
printf("层序遍历:");
BinaryTreeLevelOrder(root);
printf("\n");
//测试叶子结点个数
printf("叶子结点个数为:%d\n", BinaryTreeLeafSize(root));
//测试判断是否是完全二叉树
if (BinaryTreeComplete(root)) {
printf("该二叉树是完全二叉树\n");
} else {
printf("该二叉树不是完全二叉树\n");
}
//测试销毁树
BinaryTreeDestory(root);
root = NULL;
}
int main() {
BTNode* root = NULL;
TestBinaryTree(root);
return 0;
}
✅ 功能总结
| 功能 | 函数名 | 说明 |
|---|---|---|
| 创建 | BinaryTreeCreate | 前序遍历序列构建 |
| 销毁 | BinaryTreeDestory | 递归释放内存 |
| 节点数 | BinaryTreeSize | 递归统计 |
| 叶子数 | BinaryTreeLeafSize | 左右子节点为空 |
| 第k层节点数 | BinaryTreeLevelKSize | 递归至第k层 |
| 深度 | BinaryTreeDepth | 递归计算最大深度 |
| 查找节点 | BinaryTreeFind | 递归查找 |
| 前中后序遍历 | Prev/In/PostOrder | 递归实现 |
| 层序遍历 | LevelOrder | 队列辅助 |
| 判断完全二叉树 | BinaryTreeComplete | 层序遍历判断 |
📌 注意事项
-
使用
#表示空节点,构建时需严格对应前序遍历结构 -
层序遍历和完全二叉树判断需依赖队列实现
-
销毁二叉树后应将根指针置为
NULL,避免野指针 -
测试代码中包含了完整的交互式测试流程
&spm=1001.2101.3001.5002&articleId=152170425&d=1&t=3&u=9c490972a12946ca9547d87988485bb3)
2万+

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



