初识二叉树( 二)

embedded/2025/4/2 6:38:34/

初识二叉树 二

  • 实现链式结构二叉树
    • 前中后序遍历
      • 遍历规则
      • 代码实现
    • 结点个数以及高度等
    • 层序遍历
    • 判断是否为完全二叉树

实现链式结构二叉树

⽤链表来表示⼀棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址,其结构如下:

typedef int BTDataType;
// ⼆叉链
typedef struct BinaryTreeNode
{struct BinTreeNode* left; // 指向当前结点左孩⼦ struct BinTreeNode* right; // 指向当前结点右孩⼦ BTDataType val; // 当前结点值域 
}BTNode;

前中后序遍历

前中后序遍历,均用到函数的递归,因此代码量虽小,却能够帮助我们充分理解递归的思想。

遍历规则

按照规则,⼆叉树的遍历有:前序/中序/后序的递归结构遍历:
1)前序遍历(Preorder Traversal 亦称先序遍历):访问根结点的操作发⽣在遍历其左右子树之前
访问顺序为:根结点、左子树、右子树
2)中序遍历(Inorder Traversal):访问根结点的操作发⽣在遍历其左右子树之中(间)
访问顺序为:左子树、根结点、右子树
3)后序遍历(Postorder Traversal):访问根结点的操作发⽣在遍历其左右子树之后
访问顺序为:左⼦树、右⼦树、根结点

代码实现

void PreOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%d ", root->val);PreOrder(root->left);PreOrder(root->right);
}
void InOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}InOrder(root->left);printf("%d ", root->val);InOrder(root->right);
}
void PostOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}InOrder(root->left);InOrder(root->right);printf("%d ", root->val);
}

结点个数以及高度等

// ⼆叉树结点个数 
int BinaryTreeSize(BTNode* root); 
// ⼆叉树叶⼦结点个数 
int BinaryTreeLeafSize(BTNode* root); 
// ⼆叉树第k层结点个数 
int BinaryTreeLevelKSize(BTNode* root, int k); 
//⼆叉树的深度/⾼度
int BinaryTreeDepth(BTNode* root);
// ⼆叉树查找值为x的结点 
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// ⼆叉树销毁
void BinaryTreeDestory(BTNode** root);

层序遍历

除了先序遍历、中序遍历、后序遍历外,还可以对⼆叉树进⾏层序遍历。设⼆叉树的根结点所在层数为1,层序遍历就是从所在⼆叉树的根结点出发,⾸先访问第⼀层的树根结点,然后从左到右访问第2层上的结点,接着是第三层的结点,以此类推,⾃上⽽下,⾃左⾄右逐层访问树的结点的过程就是层序遍历实现层序遍历需要额外借助数据结构:队列
在这里插入图片描述

// 层序遍历
void LevelOrder(BTNode* root)
{Queue q;QueueInit(&q);QueuePush(&q, root);while (!QueueEmpty(&q)){BTNode* top = QueueFront(&q);printf("%c ", top->data);QueuePop(&q);if (top->_left) {QueuePush(&q, top->_left);}if (top->_right) {QueuePush(&q, top->_right);}}QueueDesTroy(&q);
}

判断是否为完全二叉树

// 判断⼆叉树是否是完全⼆叉树
bool BinaryTreeComplete(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 != NULL) {QueueDesTroy(&q);return false;}}QueueDesTroy(&q);return true;
}
```利用了队列的方法,将二叉树进行遍历,一旦在NULL后找到非空元素,说明该二叉树非完全二叉树,若全不为空,或剩下的全为空时,说明为完全二叉树,但有一点需要判断该队列是否为空。

http://www.ppmy.cn/embedded/134585.html

相关文章

java常用数据结构及其接口

Java 提供了丰富的集合框架及其数据结构,每个结构和接口都有独特的功能。以下是一些常用的数据结构和接口,以及它们的关键方法: ### 接口及其实现 1. **List 接口** - 实现类:ArrayList、LinkedList、Vector - 关键方法&a…

socket编程---UDP

目录 一、socket 二、socket接口 1.流程原理 2.代码 前言 提示:这里可以添加本文要记录的大概内容: socket编程又称套接字编程,指进行网络通信程序的编写 提示:以下是本篇文章正文内容,下面案例可供参考 一、soc…

UDP组播测试

支持组播的接口: ip a | grep MULTICAST 环回接口虽然显示不支持组播,实际也可以用于本地测试。 添加路由(非必须?): ip route add 239.0.0.0/24 via 10.10.10.206 dev eth0 开放防火墙: 查…

将机器人六轴坐标转为4*4矩阵(Opencv/C++)

已知机器人六轴坐标x,y,z,rx,ry,rz&#xff0c;其中xyz表示空间位置坐标&#xff0c;rx,ry,rz是欧拉角&#xff1b; 需要将这六个值转为4*4的矩阵以便后续其它处理运算。 代码如下&#xff1a; #include <opencv2/core.hpp> #include <iostream> #include <cm…

解决Redis缓存穿透(缓存空对象、布隆过滤器)

文章目录 背景代码实现前置实体类常量类工具类结果返回类控制层 缓存空对象布隆过滤器结合两种方法 背景 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库 常见的解决方案有两种&#xff0c;分别…

江协科技STM32学习- P30 FlyMCU串口下载STLink Utility

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

【缓存与加速技术实践】NoSQL之Redis部署安装与基础命令

文章目录 关系型数据库与非关系型数据库关系型数据库SQL定义SQL语句主流产品 非关系型数据库NoSQL定义主流产品 区别数据存储方式不同扩展方式不同对事务性的支持不同应用场景结构对比 补充 RedisRedis 的特点与优势Redis 的使用场景哪些数据适合放入缓存中&#xff1f;Redis 为…

构建安全的用户登录API:从请求验证到JWT令牌生成

构建安全的用户登录API&#xff1a;从请求验证到JWT令牌生成 为了实现这个后端POST /api/users/login端点&#xff0c;我们可以使用Node.js和Express框架&#xff0c;并结合一些常用的库如jsonwebtoken、bcrypt和express-validator来处理验证和密码校验。下面是一个完整的示例…