c/c++蓝桥杯经典编程题100道(17)二叉树遍历

二叉树遍历

->返回c/c++蓝桥杯经典编程题100道-目录


目录

二叉树遍历

一、题型解释

二、例题问题描述

三、C语言实现

解法1:递归前序遍历(难度★)

解法2:迭代中序遍历(难度★★)

解法3:层次遍历(BFS,难度★★)

四、C++实现

解法1:递归后序遍历(难度★)

解法2:迭代前序遍历(难度★★)

解法3:锯齿形层次遍历(难度★★★)

五、总结对比表

六、特殊方法与内置函数补充

1. C++ STL容器

2. Morris遍历算法(C语言示例)


一、题型解释

二叉树遍历是按照特定顺序访问树中所有节点的操作。常见题型:

  1. 基础遍历:前序、中序、后序遍历(递归或迭代实现)。

  2. 层次遍历(BFS):按层从上到下访问节点。

  3. 变种遍历

    • 锯齿形层次遍历(Zigzag遍历)。

    • 垂序遍历(按列访问节点)。

  4. Morris遍历:使用线索二叉树实现O(1)空间复杂度的遍历。


二、例题问题描述

例题1:输入二叉树:

    1  / \  2   3  / \  
4   5

前序遍历输出 1 2 4 5 3,中序遍历输出 4 2 5 1 3,后序遍历输出 4 5 2 3 1

例题2:输入同上二叉树,层次遍历输出 1 2 3 4 5
例题3:锯齿形层次遍历输出 1 3 2 4 5(第二层反向)。


三、C语言实现

解法1:递归前序遍历(难度★)

通俗解释

  • 像“根→左→右”的顺序探访每个房间,先访问根节点,再递归访问左右子树。

c

#include <stdio.h>
#include <stdlib.h>typedef struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
} TreeNode;void preorderTraversal(TreeNode *root) {if (root == NULL) return;printf("%d ", root->val);  // 先访问根节点preorderTraversal(root->left);  // 递归左子树preorderTraversal(root->right); // 递归右子树
}int main() {// 构建例题1的二叉树TreeNode n4 = {4, NULL, NULL};TreeNode n5 = {5, NULL, NULL};TreeNode n2 = {2, &n4, &n5};TreeNode n3 = {3, NULL, NULL};TreeNode n1 = {1, &n2, &n3};printf("前序遍历:");preorderTraversal(&n1); // 输出 1 2 4 5 3return 0;
}

代码逻辑

  1. 递归终止条件:当前节点为NULL时返回。

  2. 访问顺序:根节点→左子树→右子树。

  3. 时间复杂度:O(n),每个节点访问一次。


解法2:迭代中序遍历(难度★★)

通俗解释

  • 用栈模拟递归过程,像“先深入左子树到底,再回溯访问根节点,最后处理右子树”。

c

#include <stdbool.h>
#define MAX_SIZE 100typedef struct Stack {TreeNode* data[MAX_SIZE];int top;
} Stack;void push(Stack *s, TreeNode *node) {s->data[++s->top] = node;
}TreeNode* pop(Stack *s) {return s->data[s->top--];
}bool isEmpty(Stack *s) {return s->top == -1;
}void inorderTraversal(TreeNode *root) {Stack s = { .top = -1 };TreeNode *curr = root;while (curr != NULL || !isEmpty(&s)) {while (curr != NULL) { // 深入左子树push(&s, curr);curr = curr->left;}curr = pop(&s);        // 回溯到父节点printf("%d ", curr->val);curr = curr->right;    // 处理右子树}
}int main() {printf("\n中序遍历:");inorderTraversal(&n1); // 输出 4 2 5 1 3return 0;
}

代码逻辑

  1. 栈辅助:用栈保存未处理的节点。

  2. 左链入栈:不断将左子节点压栈,直到最左端。

  3. 回溯访问:弹出栈顶节点访问,转向右子树。


解法3:层次遍历(BFS,难度★★)

通俗解释

  • 像逐层扫描,用队列记录每层节点,先访问上层再下层。

c

#include <stdbool.h>
#define MAX_SIZE 100typedef struct Queue {TreeNode* data[MAX_SIZE];int front, rear;
} Queue;void enqueue(Queue *q, TreeNode *node) {q->data[q->rear++] = node;
}TreeNode* dequeue(Queue *q) {return q->data[q->front++];
}bool isEmpty(Queue *q) {return q->front == q->rear;
}void levelOrderTraversal(TreeNode *root) {if (root == NULL) return;Queue q = { .front = 0, .rear = 0 };enqueue(&q, root);while (!isEmpty(&q)) {TreeNode *node = dequeue(&q);printf("%d ", node->val);if (node->left) enqueue(&q, node->left);if (node->right) enqueue(&q, node->right);}
}int main() {printf("\n层次遍历:");levelOrderTraversal(&n1); // 输出 1 2 3 4 5return 0;
}

代码逻辑

  1. 队列初始化:根节点入队。

  2. 循环处理:出队节点并访问,将其子节点入队。

  3. 逐层遍历:队列先进先出特性保证按层访问。


四、C++实现

解法1:递归后序遍历(难度★)

通俗解释

  • 按“左→右→根”顺序访问,先处理左右子树,最后访问根节点。

cpp

#include <iostream>
using namespace std;struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};void postorderTraversal(TreeNode *root) {if (!root) return;postorderTraversal(root->left);  // 先左子树postorderTraversal(root->right); // 再右子树cout << root->val << " ";        // 最后根节点
}int main() {TreeNode *root = new TreeNode(1);root->left = new TreeNode(2);root->right = new TreeNode(3);root->left->left = new TreeNode(4);root->left->right = new TreeNode(5);cout << "后序遍历:";postorderTraversal(root); // 输出 4 5 2 3 1return 0;
}

代码逻辑

  • 与C语言递归类似,但使用C++的类和指针语法。


解法2:迭代前序遍历(难度★★)

通俗解释

  • 用栈模拟递归,显式控制访问顺序(根→左→右)。

cpp

#include <stack>
void preorderIterative(TreeNode *root) {if (!root) return;stack<TreeNode*> s;s.push(root);while (!s.empty()) {TreeNode *node = s.top();s.pop();cout << node->val << " ";if (node->right) s.push(node->right); // 右子先入栈(后处理)if (node->left) s.push(node->left);   // 左子后入栈(先处理)}
}int main() {cout << "\n迭代前序遍历:";preorderIterative(root); // 输出 1 2 4 5 3return 0;
}

代码逻辑

  1. 根节点入栈:栈顶为当前访问的根节点。

  2. 右子先入栈:利用栈的LIFO特性,确保左子先被处理。


解法3:锯齿形层次遍历(难度★★★)

通俗解释

  • 层次遍历的变种,偶数层反向输出(用双端队列控制方向)。

cpp

#include <queue>
#include <vector>
void zigzagLevelOrder(TreeNode *root) {if (!root) return;queue<TreeNode*> q;q.push(root);bool leftToRight = true;while (!q.empty()) {int size = q.size();vector<int> level(size);for (int i = 0; i < size; i++) {TreeNode *node = q.front();q.pop();int index = leftToRight ? i : size - 1 - i;level[index] = node->val;if (node->left) q.push(node->left);if (node->right) q.push(node->right);}leftToRight = !leftToRight;for (int num : level) cout << num << " ";}
}int main() {cout << "\n锯齿形遍历:";zigzagLevelOrder(root); // 输出 1 3 2 4 5return 0;
}

代码逻辑

  1. 队列记录当前层:每次处理一层节点。

  2. 方向控制:根据层数奇偶性决定填充顺序。


五、总结对比表

方法时间复杂度空间复杂度优点缺点
递归遍历O(n)O(n)代码简洁栈溢出风险
迭代遍历O(n)O(n)无栈溢出风险需手动管理栈/队列
层次遍历(BFS)O(n)O(n)直观,适合按层处理空间占用较大
Morris遍历O(n)O(1)无需额外空间修改树结构,逻辑复杂

六、特殊方法与内置函数补充

1. C++ STL容器

  • stack<TreeNode*>:用于迭代遍历,支持 push()pop()top()

  • queue<TreeNode*>:用于层次遍历,支持 push()front()pop()

2. Morris遍历算法(C语言示例)

通俗解释

  • 通过修改树的指针,将空间复杂度降为O(1)。

c

void morrisInorder(TreeNode *root) {TreeNode *curr = root, *pre;while (curr != NULL) {if (curr->left == NULL) { // 无左子树,直接访问printf("%d ", curr->val);curr = curr->right;} else {pre = curr->left;while (pre->right != NULL && pre->right != curr) {pre = pre->right; // 找到左子树的最右节点}if (pre->right == NULL) { // 建立线索pre->right = curr;curr = curr->left;} else { // 删除线索并访问pre->right = NULL;printf("%d ", curr->val);curr = curr->right;}}}
}

代码逻辑

  1. 线索化:将当前节点的前驱节点的右指针指向自己,实现回溯。

  2. 遍历与恢复:访问后删除线索,恢复树结构。

c/c++蓝桥杯经典编程题100道-目录-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14611.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cs106x-lecture2(上)(Autumn 2017)

打卡cs106x(Autumn 2017)-lecture2 1、parameterMysteryBCA What is the output of the following code? void mystery(int& b, int c, int& a) {a;b--;c a; } ​ int main() {int a 5;int b 2;int c 8;mystery(c, a, b);cout << a << " "…

e2studio开发RA2E1(9)----定时器GPT配置输入捕获

e2studio开发RA2E1.9--定时器GPT配置输入捕获 概述视频教学样品申请硬件准备参考程序源码下载选择计时器时钟源UART配置UART属性配置设置e2studio堆栈e2studio的重定向printf设置R_SCI_UART_Open()函数原型回调函数user_uart_callback ()printf输出重定向到串口定时器输入捕获配…

JVM虚拟机以及跨平台原理

相信大家已经了解到Java具有跨平台的特性&#xff0c;即“一次编译&#xff0c;到处运行”&#xff0c;例如在Windows下编写的程序&#xff0c;无需任何修改就可以在Linux下运行&#xff0c;这是C和C很难做到的。 那么&#xff0c;跨平台是怎样实现的呢&#xff1f;这就要谈及…

激活函数篇 02 —— 双曲正切函数tanh

本篇文章收录于专栏【机器学习】 以下是激活函数系列的相关的所有内容: 一文搞懂激活函数在神经网络中的关键作用 逻辑回归&#xff1a;Sigmoid函数在分类问题中的应用 tanh ⁡ ( x ) e x − e − x e x e − x \tanh(x)\frac{e^x - e^{-x}}{e^x e^{-x}} tanh(x)exe−xex…

redis高级数据结构布隆过滤器

文章目录 背景什么是布隆过滤器Redis 中的布隆过滤器布隆过滤器使用注意事项实现原理空间占用估计 背景 我们在使用新闻客户端看新闻时&#xff0c;它会给我们不停地推荐新的内容&#xff0c;它每次推荐时要去重&#xff0c;去掉那些已经看过的内容。问题来了&#xff0c;新闻…

存储异常导致的Oracle重大生产故障

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验 Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯…

在 Navicat 17 中扩展 PostgreSQL 数据类型 | 创建自定义域

定义域 以适当的格式存储数据可以确保数据完整性&#xff0c;防止错误&#xff0c;优化性能&#xff0c;并通过实施验证规则和支持高效数据管理来维护系统间的一致性。基于这些原因&#xff0c;顶级关系数据库&#xff08;如PostgreSQL&#xff09;提供了多种数据类型。此外&a…

计算机视觉-拟合

一、拟合 拟合的作用主要是给物体有一个更好的描述 根据任务选择对应的方法&#xff08;最小二乘&#xff0c;全最小二乘&#xff0c;鲁棒最小二乘&#xff0c;RANSAC&#xff09; 边缘提取只能告诉边&#xff0c;但是给不出来数学描述&#xff08;应该告诉这个点线是谁的&a…

oracle基础语法

oracle基础语法 1、增删改查1.1查询语句1.2 修改语句1.3 删除表1.4 删除数据1.5 增加数据1.6 创建视图1.7 添加视图字段注释 1、增删改查 oracle与sql server语法上大致相同&#xff0c;但有些细微的不同&#xff0c;以下是我个人记录工作中常用到的一些语法句。 1.1查询语句…

CodeGPT + IDEA + DeepSeek,在IDEA中引入DeepSeek实现AI智能开发

CodeGPT IDEA DeepSeek&#xff0c;在IDEA中引入DeepSeek 版本说明 建议和我使用相同版本&#xff0c;实测2022版IDEA无法获取到CodeGPT最新版插件。&#xff08;在IDEA自带插件市场中搜不到&#xff0c;可以去官网搜索最新版本&#xff09; ToolsVersionIntelliJ IDEA202…

星网锐捷 视频话机设备pwdsetting管理密码信息泄漏

星网锐捷 视频话机设备pwdsetting管理密码信息泄漏 漏洞描述 星网锐捷视频话机设备 泄露管理员密码&#xff0c;攻击者可利用密码直接进入后台配置页面&#xff0c;执行恶意操作&#xff0c;进行一步攻击。 威胁等级: 高危 漏洞分类: 信息泄露 涉及厂商及产品&#xff1a;…

网络安全 | 保护智能家居和企业IoT设备的安全策略

网络安全 | 保护智能家居和企业IoT设备的安全策略 一、前言二、智能家居和企业 IoT 设备面临的安全威胁2.1 设备自身安全缺陷2.2 网络通信安全隐患2.3 数据隐私风险2.4 恶意软件和攻击手段 三、保护智能家居和企业 IoT 设备的安全策略3.1 设备安全设计与制造环节的考量3.2 网络…

38、【OS】【Nuttx】OSTest分析(3):参数传递

背景 接之前 blog 36、【OS】【Nuttx】OSTest分析&#xff08;2&#xff09;&#xff1a;环境变量测试 37、【OS】【Nuttx】OSTest分析&#xff08;2&#xff09;&#xff1a;任务创建 分析完环境变量测试&#xff0c;和任务创建的一些关键要素&#xff0c;OSTest 进入下一阶段…

储能系统-系统架构

已更新系列文章包括104、61850、modbus 、单片机等&#xff0c;欢迎关注 IEC61850实现方案和测试-1-CSDN博客 快速了解104协议-CSDN博客 104调试工具2_104协议调试工具-CSDN博客 1 电池储能系统&#xff08;BESS&#xff09; 架构 电池储能系统主要包括、电池、pcs、本地控制…

Listener监听器和Filter过滤器

一.监听器 1.是javaweb的三大组件之一,分别是Servlet程序,Listener监听器,Filter过滤器 2.Listener是JvaEE的规范,就是接口,监听器的作用就是监听某种变化(一般是对象创建/销毁,属性变化),触发对应方法完成相应的任务 3.ServletContextListener:/*当一个类实现了ServletContex…

Go 中的 7 个常见接口错误

Go 仍然是一门新语言,如果你正在使用它,它很可能不是你的第一门编程语言。 不同的语言,既为你带来了经验,也带来了偏见。你用以前的任何语言做的事情,在 Go 中用相同的方法可能不是一个好主意。 学习 Go 不仅仅是学习一种新的语法。这也是学习一种新的思维方式来思考你的…

【AI实践】Cursor上手-跑通Hello World和时间管理功能

背景 学习目的&#xff1a;熟悉Cursor使用环境&#xff0c;跑通基本开发链路。 本人背景&#xff1a;安卓开发不熟悉&#xff0c;了解科技软硬件常识 实践 基础操作 1&#xff0c;下载安装安卓Android Studio 创建一个empty project 工程&#xff0c;名称为helloworld 2&am…

存储系统、网盘系统的访问留痕

一、适用场景 1、需要了解是否存在非法访问存储系统或网盘系统&#xff1a;各企业或单位为方便远程办公或远程管理&#xff0c;若自建&#xff08;保护隐私数据或敏感资料&#xff09;了存储系统或网盘系统&#xff0c;那么到底有哪些ip地址或用户从远程公网访问存储系统或网盘…

求助DeepSeek帮我开发一个直线审批流程设计页面Vue2.0

之前使用文心一言协助开发过类似的页面&#xff0c;需求方认为某些业务表单需要添加审批流程&#xff0c;可以人为设置审批步骤&#xff0c;由于需求很模糊而且人/天有限&#xff0c;当时的提问很混乱&#xff0c;内容如下&#xff1a; 我的vue2.0系统中需要审批流程设计页面&a…

初级数据结构:栈和队列

目录 一、栈 (一)、栈的定义 (二)、栈的功能 (三)、栈的实现 1.栈的初始化 2.动态扩容 3.压栈操作 4.出栈操作 5.获取栈顶元素 6.获取栈顶元素的有效个数 7.检查栈是否为空 8.栈的销毁 9.完整代码 二、队列 (一)、队列的定义 (二)、队列的功能 (三&#xff09…