当前位置: 首页 > news >正文

7、二叉树-四种遍历方式

二叉树的遍历是数据结构中的核心操作之一,主要包括以下四种方式:前序遍历中序遍历后序遍历层次遍历


示例二叉树结构

根节点为 A,A 的左子节点 B,右子节点 C;B 的左子节点 D,右子节点 E;C 的右子节点 F。

结构描述:

        A/ \B   C/ \   \D   E   F

🌳 四种常见遍历方式

  1. 前序遍历(Preorder)
    访问顺序:根节点 → 左子树 → 右子树
    常用于复制树结构或表达式树的前缀表达式。
 void preorder(TreeNode* root) {if (!root) return;printf("%d ", root->val);preorder(root->left);preorder(root->right);
}
  • 输出结果
  • 访问顺序示例:A → B → D → E → C → F
  • 直观场景:把一棵树序列化为“先看父节点再看子节点”的顺序,适合生成前缀表达式或复制树结构(先记录节点,再记录子结构)。
  1. 中序遍历(Inorder)
    访问顺序:左子树 → 根节点 → 右子树
    在二叉搜索树中,中序遍历可以得到有序序列。
void inorder(TreeNode* root) {if (!root) return;inorder(root->left);printf("%d ", root->val);inorder(root->right);
}
  • 输出结果
  • 访问顺序示例:D → B → E → A → C → F
  • 直观场景:在二叉搜索树中按中序遍历会得到从小到大的有序序列,适合做排序输出或中序表达式(中缀表达式)。
  1. 后序遍历(Postorder)
    访问顺序:左子树 → 右子树 → 根节点
    常用于删除树或表达式树的后缀表达式。
void postorder(TreeNode* root) {if (!root) return;postorder(root->left);postorder(root->right);printf("%d ", root->val);
}
  • 输出结果
  • 访问顺序示例:D → E → B → F → C → A
  • 直观场景:在删除节点或释放资源时先处理子节点再处理父节点;构造后缀表达式或在合并子结果后计算父节点值(先算子,再算父)。
  1. 层次遍历(Level Order)
    按照树的层级逐层访问,通常使用队列实现。
    适合用于图形化展示或查找最短路径等问题。
void levelOrder(TreeNode* root) {if (!root) return;Queue q; initQueue(&q);enqueue(&q, root);while (!isEmptyQueue(&q)) {TreeNode* node = dequeue(&q);printf("%d ", node->val);if (node->left) enqueue(&q, node->left);if (node->right) enqueue(&q, node->right);}
}
  • 输出结果
  • 访问顺序示例:A → B → C → D → E → F
  • 直观场景:按层级展示或逐层处理(例如计算树的层数、找最短路径层次、做按层统计),常用于 BFS(广度优先搜索)场景。

递归的本质就是栈

递归依赖于调用栈来保存每次函数调用的状态。每次递归调用都会在栈上压入一个栈帧,栈帧包含参数、局部变量和返回地址。当前调用完成后该栈帧弹出,控制权返回到上一次调用处。

  • 对于二叉树遍历,递归过程实际等价于把节点按访问路径压入栈,然后再逐个弹出并处理。
  • 递归可以用显式栈结构等价地改写为迭代版本,功能完全相同但控制权由程序员显式管理。
  • 优点:代码简洁、逻辑直观。
  • 缺点:深度过大可能导致栈溢出。某些语言或编译器对尾递归有优化可以避免额外栈开销,但 C 语言不保证尾递归优化。

c代码实现

#include<stdio.h>
#include <stdlib.h>typedef struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
}TNode;// 递归前序遍历
void PrevOrder(TNode* root)
{if(root == NULL){printf("NULL ");return;}printf("%d ",root->val);PrevOrder(root->left);PrevOrder(root->right);}// 递归中序遍历
void InOrder(TNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%d ", root->val);InOrder(root->right);
}// 递归后序遍历
void PostOrder(TNode* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->val);
}// 二叉树大小
int TreeSize(TNode* root)
{if (root == NULL)return 0;return 1 + TreeSize(root->left) + TreeSize(root->right);// 其实所有的数据增加都是靠这个1走到根部之后都是0}// 如果我只想要叶子节点的个数呢
int LeafCount(TNode* root)
{if (root == NULL)return 0;if (root->left == NULL && root->right == NULL)return 1;return LeafCount(root->left) + LeafCount(root->right);
}int TreeDepth(TNode* root)
{if (root == NULL)return 0;int leftDepth = TreeDepth(root->left);int rightDepth = TreeDepth(root->right);return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
}TNode* newNode(int v) {TNode* p = (TNode*)malloc(sizeof(TNode));if (!p) return NULL;p->val = v;p->left = p->right = NULL;return p;
}TNode* buildExampleTree() {TNode* A = newNode(1); // ATNode* B = newNode(2); // BTNode* C = newNode(3); // CTNode* D = newNode(4); // DTNode* E = newNode(5); // ETNode* F = newNode(6); // FA->left  = B;A->right = C;B->left  = D;B->right = E;C->left  = NULL;C->right = F;return A;
}
/*
创建的二叉树的直观结构A/ \B   C/ \   \D   E   F
*/void freeTree(TNode* root) {if (!root) return;freeTree(root->left);freeTree(root->right);free(root);
}int main(){TNode* A = buildExampleTree();PrevOrder(A);printf("\n");InOrder(A);printf("\n");PostOrder(A);printf("\n");int size = TreeSize(A);printf("Tree size = %d\n", size); // 预期输出:Tree size = 6freeTree(A);return 0;}

文章转载自:

http://eeqSQUYz.qLpyn.cn
http://xVPU5dl0.qLpyn.cn
http://Naqfi0Lv.qLpyn.cn
http://3MvQSWvA.qLpyn.cn
http://X5QyqMR7.qLpyn.cn
http://qT3At5q0.qLpyn.cn
http://5yy1EPvq.qLpyn.cn
http://xZzPrmrb.qLpyn.cn
http://SUbalKMb.qLpyn.cn
http://4I5tz6eS.qLpyn.cn
http://Angf7V1m.qLpyn.cn
http://a3FcnEoV.qLpyn.cn
http://Ht4JUeSj.qLpyn.cn
http://sPNMpms6.qLpyn.cn
http://D2Xy1eC6.qLpyn.cn
http://W8gSUJJe.qLpyn.cn
http://N0XWm7dO.qLpyn.cn
http://EycDGwU4.qLpyn.cn
http://8jGrztNZ.qLpyn.cn
http://kXGA9egb.qLpyn.cn
http://KbK1Qq7U.qLpyn.cn
http://yKS5wGJd.qLpyn.cn
http://Xv2GzMW3.qLpyn.cn
http://I349R8hE.qLpyn.cn
http://ynb4ZO3m.qLpyn.cn
http://37NMiPnY.qLpyn.cn
http://iRGTQ1z3.qLpyn.cn
http://JdshYAij.qLpyn.cn
http://ApcaHOEC.qLpyn.cn
http://bu84C0ah.qLpyn.cn
http://www.dtcms.com/a/387741.html

相关文章:

  • 双指针:逛画展
  • 数字孪生能源大数据云平台建设方案
  • WPSOffice引用的组件
  • 按键分区和非按键分区对窗口计算的影响
  • 2020年下半年 系统架构设计师 综合知识
  • 传感器与传感网 | 第一章:传感器与感知技术
  • 在Jupyter Notebook里面渲染pyecharts无法显示
  • 在 React 项目里下载 CSV 文件常见的两种方式
  • 【脑电分析系列】第15篇:脑电功能连接性与脑网络分析(二):Granger因果性、图论指标与复杂网络构建
  • SpringMVC 系列博客(一):基础概念与注解开发入门
  • AI+Playwright+Pytest 自动化测试方案:优势、劣势与实战融合
  • docker启动Nginx并配置SSL自动续期.md
  • OpenStack 学习笔记(三):存储与计算核心组件管理实践
  • Linux文件IO与文件系统深度解析:从系统调用到文件系统原理
  • 如何在 2025 年绕过 Cloudflare 人工检查?
  • 【pycharm】index-tts2:之三 :ubuntu24.04 体验tts demo
  • vivado中DDR4 仿真模型的获取
  • 《RocketMQ 2025 实战指南:从消息丢失 / 重复消费 / 顺序消费到事务消息,一篇搞定生产级问题(附完整代码)》
  • 十二、vue3后台项目系列——设置路由守卫,获取角色权限,获取角色路由列表、页面请求进度条
  • 6个AI论文网站排行,实测
  • Dioxus基础介绍和创建组件
  • 基于粒子群算法的山地环境无人机最短路径规划研究(含危险区域约束的三维优化方法)
  • ardupilot开发 --- 无人机数学模型与控制律分解 篇
  • 海外代理IP服务器平台测评,Tik Tok多账号运营稳定IP服务支持
  • 【面板数据】省及地级市农业新质生产力数据集(2002-2025年)
  • Linux的常用命令总结
  • Egg.js:企业级 Node.js 框架的优雅实践
  • vue中v-model绑定计算属性
  • 查看磁盘分区并新建一个分区,挂载分区
  • SQL Server到Hive:批处理ETL性能提升30%的实战经验