数据结构:链表二叉树

ops/2024/10/24 21:07:21/

一、什么是二叉树?

二叉树是一种数据结构,其中每个节点最多有两个子节点,分别称为左子节点右子节点。二叉树的根节点是整个树的入口,通常我们可以通过递归的方式来访问树中的所有节点。二叉树在计算机科学中应用非常广泛,例如在表达式解析、搜索算法、排序等方面。

在这篇文章中,我们将学习如何在C语言中实现一个简单的二叉树,并讲解其各个功能模块,包括如何创建节点、遍历树、计算节点数量、查找节点等。通过这篇博客,大家会掌握如何设计和实现二叉树,避免常见的错误,并理解这些操作背后的原理。

二、程序的作用和意义

这段程序实现了一个二叉树的基本操作,包括:

  1. 节点创建:动态分配内存并创建二叉树的节点。
  2. 遍历树:通过不同的顺序(前序、中序、后序)来遍历二叉树。
  3. 计算树的信息:例如计算二叉树的节点数、叶子节点数、指定层数的节点个数、树的深度等。
  4. 查找节点:在二叉树中查找某个值。
  5. 销毁树:释放二叉树占用的内存。

这些操作是理解二叉树的重要基础,能够帮助我们更好地应用到实际问题中,比如搜索树、排序树等。

三、如何创建二叉树节点

函数:BTNode* buyNode(BTDataType x)

这个函数用于创建一个新的二叉树节点,并为其分配内存。

BTNode* buyNode(BTDataType x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL) // 检查内存分配是否成功{perror("malloc error!"); // 打印错误信息exit(1); // 终止程序}newnode->data = x; // 设置节点数据newnode->left = newnode->right = NULL; // 初始时,左右孩子指针为空return newnode; // 返回新创建的节点
}
  • 为什么要这样写?
    • 使用malloc动态分配内存,使得节点可以在程序运行时根据需要创建。
    • 每个节点的数据由data存储,并且左右孩子初始化为NULL,表示它们还没有子节点。
  • 易错点
    • 忘记检查malloc的返回值可能会导致程序崩溃,必须确保内存分配成功。
    • 忘记初始化左右孩子指针为NULL,会导致一些遍历操作发生错误。

图示:

四、如何遍历二叉树

4.1、前序遍历:PreOrder

前序遍历的顺序是:根-左-右。即首先访问当前节点,然后递归地遍历左子树,再遍历右子树。

void PreOrder(BTNode* root)
{if (root == NULL) // 如果节点为空,直接返回{return;}printf("%d ", root->data); // 先访问根节点PreOrder(root->left); // 递归访问左子树PreOrder(root->right); // 递归访问右子树
}

输出:1243

递归图如下:

  • 为什么要这样写?
    • 前序遍历首先访问根节点,再访问左子树,最后访问右子树。
  • 易错点
    • 忘记检查节点是否为空,可能导致程序访问空指针,造成崩溃。

4.2、中序遍历:InOrder

中序遍历的顺序是:左-根-右,即先遍历左子树,访问根节点,再遍历右子树。

void InOrder(BTNode* root)
{if (root == NULL){return;}InOrder(root->left); // 先递归访问左子树printf("%d ", root->data); // 访问根节点InOrder(root->right); // 再递归访问右子树
}

输出:4213

4.3、后序遍历:PostOrder

后序遍历的顺序是:左-右-根。先遍历左右子树,最后访问根节点。

void PostOrder(BTNode* root)
{if (root == NULL){return;}PostOrder(root->left); // 先递归访问左子树PostOrder(root->right); // 再递归访问右子树printf("%d ", root->data); // 最后访问根节点
}

输出:4231

五、如何计算二叉树的节点总数

函数:int BinaryTreeSize(BTNode* root)

我们可以通过递归来计算二叉树中的节点总数。对于每个节点来说,它的总节点数等于其左子树的节点数、右子树的节点数,再加上自身。

int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0; // 空节点返回0}return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
  • 为什么要这样写?
    • 每个节点的大小等于其左、右子树的大小加1(根节点本身)。
  • 易错点
    • 忘记处理root == NULL的情况,递归可能陷入死循环或崩溃。

六、如何计算二叉树的叶子节点个数

函数:int BinaryTreeLeafSize(BTNode* root)

叶子节点是没有子节点的节点,即它的leftright都是NULL。通过递归遍历整棵树,可以判断每个节点是否是叶子节点。

int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL) // 判断是否为叶子节点{return 1; // 是叶子节点,返回1}return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
  • 为什么要这样写?
    • 通过递归遍历树,并判断每个节点是否有左右孩子节点,没有孩子节点的就是叶子节点。

七、如何查找二叉树中的某个节点

函数:BTNode* BinaryTreeFind(BTNode* root, BTDataType x)

该函数用于在二叉树中查找值为x的节点。我们通过递归查找左子树和右子树,直到找到符合条件的节点。

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x) // 找到目标节点{return root;}BTNode* leftFind = BinaryTreeFind(root->left, x); // 在左子树查找if (leftFind) // 如果左子树找到,则直接返回{return leftFind;}return BinaryTreeFind(root->right, x); // 否则在右子树继续查找
}

八、如何销毁二叉树

函数:void BinaryTreeDestory(BTNode** root)

销毁二叉树时,我们需要释放每个节点所占的内存。可以使用后序遍历的方式,确保每个节点的子节点都被释放之后,才释放自己。

void BinaryTreeDestory(BTNode** root)
{if (*root == NULL){return;}BinaryTreeDestory(&((*root)->left)); // 递归销毁左子树BinaryTreeDestory(&((*root)->right)); // 递归销毁右子树free(*root); // 释放当前节点*root = NULL; // 将指针置为NULL,防止野指针
}

九、总结

这篇博客带领大家一步步实现了二叉树的基本操作。通过这些操作,大家掌握了如何创建、遍历、计算、查找和销毁二叉树。写二叉树时常见的错误包括:

  • 忘记检查空节点的情况。
  • 忘记正确地释放内存。

http://www.ppmy.cn/ops/128152.html

相关文章

医院信息化与智能化系统(7)

医院信息化与智能化系统(7) 这里只描述对应过程,和可能遇到的问题及解决办法以及对应的参考链接,并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图,可以试试PlantUML,告诉GPT你的文件结构,让他给你对应的…

10_ Linux软件安装指南:RPM、YUM、源码安装

系列文章导航:01_Linux基础操作CentOS7学习笔记-CSDN博客 文章目录 1. RPM包安装2. YUM包管理器3. 源码安装 在Linux系统中,软件安装是日常管理中的一项基本任务。本文将详细介绍三种常见的软件安装方法:RPM包安装、YUM包管理器安装和源码编…

JavaWeb 22.Node.js_简介和安装

有时候,后退原来是向前 —— 24.10.7 一、什么是Node.js Node.js 是一个于 Chrome V8 的 JavaScript 运行时环境,可以使 JavaScript 运行在服务器端。使用 Node.js,可以方便地开发服务器端应用程序,如 Web 应用、API、后端服务&a…

【mod分享】极品飞车10卡本峽谷白日mod,在白天竞速也是一种很棒的体验,更多的车辆,更高清的材质,更棒的灯光效果、同样光追

各位好,今天小编给大家带来一款新的高清重置魔改MOD,本次高清重置的游戏叫《极品飞车10卡本峡谷》。 《极品飞车10:卡本峡谷》继承了前几款游戏的开放式环境的特点,并且在此基础上做出了很大的改进。这次玩家仍旧要开着车在城市里…

leetcode3175. 找到连续赢 K 场比赛的第一位玩家,方向和细节不对,努力白费

leetcode3175. 找到连续赢 K 场比赛的第一位玩家 最开始思路 看到题目的示例,只要比较数组的前2位,就好了,但是要一直变化这个数组的值的位置 被题目的示例误导了 没有细品题意,折腾半天,原来就是不断更新最大值&…

QExcel 保存数据 (QtXlsxWriter库 编译)

QtXlsxWriter 是一个用于在 Qt 应用程序中创建和操作 Excel XLSX 文件的库。它提供了一个简单的 API,使开发者能够轻松地生成和修改 Excel 文件,而无需依赖 Microsoft Excel 或其他外部应用程序。支持初始化、写文件、读文件、格式设置、合并单元格、加粗…

DB2数据库学习(一)

启动DB2数据步骤 1 切换到用户db2inst1 1. 用户权限 实例用户: DB2 在安装时会为每个数据库实例创建一个专用的操作系统用户(如 db2inst1)。这个用户拥有管理该实例所需的特定权限。 安全性: 通过限制数据库实例的管理操作(如启动和停止&…

XGO Rider:全球首创双轮足AI机器人,集成ChatGPT,实现智能互动

近年来,AI机器人技术的飞速发展,正在改变我们的生活方式。从智能家庭助手到教育机器人,再到商业服务,人工智能机器人逐渐从传统的工业领域进入人们的日常生活。作为全球首创的桌面双轮足式AI机器人,XGO Rider通过ChatG…