数据结构---------二叉树前序遍历中序遍历后序遍历

以下是用C语言实现二叉树的前序遍历、中序遍历和后序遍历的代码示例,包括递归和非递归(借助栈实现)两种方式:

1. 二叉树节点结构体定义

#include <stdio.h>
#include <stdlib.h>// 二叉树节点结构体
typedef struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
} TreeNode;

2. 前序遍历

(ps:图来自一位前辈,非常感谢无商用)
在这里插入图片描述

2.1 递归方式
// 前序遍历递归函数
void preorderTraversalRecursive(TreeNode* root) {if (root == NULL) {return;}printf("%d ", root->val);preorderTraversalRecursive(root->left);preorderTraversalRecursive(root->right);
}

解释

  • 首先判断根节点是否为空(NULL),如果为空,说明已经遍历完或者二叉树本身就是空树,直接返回,不做任何操作。
  • 若根节点不为空,则先输出根节点的值(通过printf函数),这符合前序遍历“根节点、左子树、右子树”的顺序。
  • 接着递归调用preorderTraversalRecursive函数去遍历左子树,完成左子树的前序遍历。
  • 最后再递归调用该函数遍历右子树,完成整个二叉树的前序遍历。
2.2 非递归方式(借助栈实现)
// 前序遍历非递归函数(借助栈)
void preorderTraversalNonRecursive(TreeNode* root) {if (root == NULL) {return;}struct TreeNode *stack[100];  // 简单起见,这里假设栈的最大容量为100,可以根据实际情况调整int top = -1;stack[++top] = root;while (top >= 0) {TreeNode* current = stack[top--];printf("%d ", current->val);if (current->right!= NULL) {stack[++top] = current->right;}if (current->left!= NULL) {stack[++top] = current->left;}}
}

解释

  • 同样先判断根节点是否为空,为空则直接返回。
  • 然后创建一个数组来模拟栈(这里简单地定义了固定大小为100的数组作为栈,实际应用中可根据二叉树规模动态分配内存),并初始化栈顶指针top为 -1,表示栈为空。
  • 将根节点入栈后,进入循环,只要栈不为空(即top >= 0):
    • 取出栈顶元素(current = stack[top--]),输出其值,这模拟了访问根节点的操作。
    • 按照前序遍历先右后左的顺序将子节点入栈(因为栈是后进先出的数据结构,先入栈右子节点,后入栈左子节点,这样出栈时就能先访问左子树),如果右子节点或左子节点不为空,就将它们依次入栈,以便后续继续遍历。

3. 中序遍历

在这里插入图片描述

3.1 递归方式
// 中序遍历递归函数
void inorderTraversalRecursive(TreeNode* root) {if (root == NULL) {return;}inorderTraversalRecursive(root->left);printf("%d ", root->val);inorderTraversalRecursive(root->right);
}

解释

  • 先判断根节点是否为空,为空则返回。
  • 按照中序遍历“左子树、根节点、右子树”的顺序,首先递归调用inorderTraversalRecursive函数去遍历左子树,确保左子树的节点先被访问。
  • 当左子树遍历完后,输出根节点的值。
  • 最后再递归调用该函数遍历右子树,完成整个二叉树的中序遍历。
3.2 非递归方式(借助栈实现)
// 中序遍历非递归函数(借助栈)
void inorderTraversalNonRecursive(TreeNode* root) {if (root == NULL) {return;}struct TreeNode *stack[100];  // 假设栈最大容量为100,可按需调整int top = -1;TreeNode* current = root;while (current!= NULL || top >= 0) {while (current!= NULL) {stack[++top] = current;current = current->left;}current = stack[top--];printf("%d ", current->val);current = current->right;}
}

解释

  • 还是先判断根节点是否为空,为空则返回。
  • 创建一个栈并初始化栈顶指针,同时用current指针指向根节点。
  • 进入循环,只要current不为空或者栈不为空:
    • 先通过内层循环将当前节点及其所有左子树节点依次入栈(不断将current指向其左子节点并入栈),直到current为空,这意味着找到了最左边的节点。
    • 然后取出栈顶元素(即最左边的节点),输出其值,这模拟了访问根节点的操作(在中序遍历中此时访问的是左子树遍历完后的根节点)。
    • 最后将current更新为该节点的右子节点,以便继续遍历右子树,重复上述过程,完成中序遍历。

4. 后序遍历

在这里插入图片描述

4.1 递归方式
// 后序遍历递归函数
void postorderTraversalRecursive(TreeNode* root) {if (root == NULL) {return;}postorderTraversalRecursive(root->left);postorderTraversalRecursive(root->right);printf("%d ", root->val);
}

解释

  • 首先判断根节点是否为空,为空则返回,不做后续操作。
  • 按照后序遍历“左子树、右子树、根节点”的顺序,先递归调用postorderTraversalRecursive函数遍历左子树。
  • 接着递归调用该函数遍历右子树。
  • 最后输出根节点的值,完成整个二叉树的后序遍历。
4.2 非递归方式(借助栈实现)
// 后序遍历非递归函数(借助栈)
void postorderTraversalNonRecursive(TreeNode* root) {if (root == NULL) {return;}struct TreeNode *stack1[100];  // 假设栈1最大容量为100,可按需调整struct TreeNode *stack2[100];  // 假设栈2最大容量为100,可按需调整int top1 = -1, top2 = -1;stack1[++top1] = root;while (top1 >= 0) {TreeNode* current = stack1[top1--];stack2[++top2] = current;if (current->left!= NULL) {stack1[++top1] = current->left;}if (current->right!= NULL) {stack1[++top1] = current->right;}}while (top2 >= 0) {printf("%d ", stack2[top2--]->val);}
}

解释

  • 先判断根节点是否为空,为空则返回。
  • 创建两个栈stack1stack2(这里同样是简单地假设了固定大小为100的数组来模拟栈,实际可按需优化),以及对应的栈顶指针top1top2,并将根节点入stack1
  • 在第一个循环中:
    • stack1中取出栈顶元素,放入stack2中,这一步是为了后续能按后序遍历的顺序输出节点。
    • 然后按照后序遍历先左后右的顺序将其左子节点和右子节点(如果存在)依次入stack1,方便后续处理。
  • 第一个循环结束后,stack2中存储的节点顺序就是后序遍历的顺序了,通过第二个循环依次输出stack2中节点的值,完成二叉树的后序遍历。

你可以使用以下代码来测试这些遍历函数:

int main() {// 构建一个简单的二叉树示例TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));root->val = 1;root->left = (TreeNode*)malloc(sizeof(TreeNode));root->left->val = 2;root->left->right = (TreeNode*)malloc(sizeof(TreeNode));root->left->right->val = 4;root->right = (TreeNode*)malloc(sizeof(TreeNode));root->right->val = 3;root->right->left = (TreeNode*)malloc(sizeof(TreeNode));root->right->left->val = 5;// 测试前序遍历printf("前序遍历(递归)结果:");preorderTraversalRecursive(root);printf("\n");printf("前序遍历(非递归)结果:");preorderTraversalNonRecursive(root);printf("\n");// 测试中序遍历printf("中序遍历(递归)结果:");inorderTraversalRecursive(root);printf("\n");printf("中序遍历(非递归)结果:");inorderTraversalNonRecursive(root);printf("\n");// 测试后序遍历printf("后序遍历(递归)结果:");postorderTraversalRecursive(root);printf("\n");printf("后序遍历(非递归)结果:");postorderTraversalNonRecursive(root);printf("\n");return 0;
}

在上述main函数中,构建了一个简单的二叉树示例,然后分别调用不同的遍历函数并输出结果,方便直观地看到不同遍历方式的效果。实际应用中,你可以根据实际的二叉树结构来进行相应的测试和使用这些遍历方法。

在这里插入图片描述

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

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

相关文章

UE5仿漫威争锋灵蝶冲刺技能

这两天玩了一下漫威争锋Marvel Rivals&#xff0c;发现是UE5做的&#xff0c;对里面一些角色技能挺感兴趣的&#xff0c;想简单复刻一下技能功能&#xff0c;顺便复习一下学过的知识 首先把摄像机设置调整一下 CameraBoom里搜索lag 把摄像机延迟关掉 &#xff0c;这样摄像机就…

常用类晨考day15

1.基本数据类型以及对应包装类 Byte Short Integer Long Float Double Boolean Character 2.什么是自动拆箱和装箱&#xff0c;jdk版本有什么要求&#xff1f;代码举 例并标明 Integer a 100; // 装箱 int b a; // 拆箱 从JDK1.5才开始支持 3.NumberFormatException是什么异常…

etcd+京东hotkey探测使用

qhotKey链接 京东hotkey把热点数据默认缓存在了本地缓存caffeine中&#xff0c;也可以存到redis中&#xff0c;但是京东hotkey的SDK没有redis的实现方法&#xff0c;因此需要自己实现。 官方目录结构下&#xff1a;分别是client客户端&#xff08;要打包引入到自己的项目&…

如何实现层叠布局

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了GirdView Widget,本章回中将介绍Stack这种Widget,闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 在Flutter中Stack主要用来叠加显示其它的Widget,类似我们日常生活中的楼层或者说PS中的图层,因此它也是一…

Java 上机实践11(组件及事件处理)

&#xff08;大家好&#xff0c;今天分享的是Java的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 Plug&#xff1a;程序实现 方法一&#xff08;记事本&#xff09; 方法二&#xff08;IDEA&#xff09; 实验一&am…

本地如何启动casdoor

1、下载代码 GitHub - casdoor/casdoor at v1.777.0 下载对应tag的代码&#xff0c;我这里选择的时v1.777.0版本 通过网盘分享的文件&#xff1a;casdoor-1.777.0.zip 链接: https://pan.baidu.com/s/1fPNqyJYeyfZnem_LtEc0hw 提取码: avpd 2、启动后端 1、使用goland编译…

CSDN外链失效3:

参考我之前的博客&#xff1a; 外链失效博客1&#xff1a;随想笔记1&#xff1a;CSDN写博客经常崩溃&#xff0c;遇到外链图片转存失败怎么办_csdn外链图片转存失败-CSDN博客 外链失效博客2&#xff1a;网络随想2&#xff1a;转语雀_md格式转语雀lake格式-CSDN博客 markdown…

Kubernates

kubernates是一个开源的&#xff0c;用于管理云平台中多个主机上的容器化的应用&#xff0c;Kubernetes的目标是让部署容器化的应用简单并且高效&#xff08;powerful&#xff09;,Kubernetes提供了应用部署&#xff0c;规划&#xff0c;更新&#xff0c;维护的一种机制。 架构…

Pycharm 更改字体大小

更改代码字体的大小 更改软件字体的大小

Ubuntu20.04解决docker安装后is the docker daemon running? 问题

Ubuntu20.04解决docker安装后is the docker daemon running? 问题 问题描述问题分析问题解决 问题描述 docker info后报错 ERROR: Cannot connect to the Docker daemon at unix:///root/.docker/desktop/docker.sock. Is the docker daemon running? errors pretty printi…

四、使用langchain搭建RAG:金融问答机器人--构建web应用,问答链,带记忆功能

经过前面3节完成金融问答机器人基本流程&#xff0c;这章将使用Gradio构建web应用&#xff0c;同时加入memory令提示模板带有记忆的&#xff0c;使用LCEL构建问答链。 加载向量数据库 from langchain.vectorstores import Chroma from langchain_huggingface import HuggingF…

深度学习之超分辨率算法——SRCNN

网络为基础卷积层 tensorflow 1.14 scipy 1.2.1 numpy 1.16 大概意思就是针对数据&#xff0c;我们先把图片按缩小因子照整数倍进行缩减为小图片&#xff0c;再针对小图片进行插值算法&#xff0c;获得还原后的低分辨率的图片作为标签。 main.py 配置文件 from model im…

基于海思soc的智能产品开发(mcu读保护的设置)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于市场上的产品&#xff0c;除了电路之外&#xff0c;软件保护也是非常重要的一个环节。要是自己辛辛苦苦写的软件&#xff0c;被竞争对手轻易地…

Zabbix6.0升级为6.4

为了体验一些新的功能&#xff0c;比如 Webhook 和问题抑制等&#xff0c;升级个小版本。 一、环境信息 1. 版本要求 一定要事先查看官方文档&#xff0c;确认组件要求的版本&#xff0c;否则版本过高或者过低都会出现问题。 2. 升级前后信息 环境升级前升级后操作系统CentOS…

GitLab的卸载与重装

目录 一、GitLab的卸载 二、 GitLab的安装与配置 1. 创建安装目录 2. 安装 3. 使用 3.1 初始化 3.2 创建空白项目 ​编辑 3.3 配置SSH 3.3.1 配置公钥 ​编辑 3.3.2 配置私钥 3.4 配置本地git库 一、GitLab的卸载 1. 停止gitlab sudo gitlab-ctl stop 2. 卸载…

Linux快速入门-Linux的常用命令

Linux的常用命令 1. Linux的终端与工作区1.1 终端概述1.2 切换终端 2. Shell语言解释器2.1 Shell概述 3. 用户登录与身份切换3.1 su 命令3.2 sudo 命令 4. 文件、目录操作命令4.1 pwd 命令4.2 cd 命令4.3 ls 命令4.3.1 ls 指令叠加使用 4.4 mkdir 命令4.5 rmdir 命令4.6 cp 命令…

三、ubuntu18.04安装docker

1.使用默认ubuntu存储库安装docker 更新软件存储库 更新本地软件数据库确保可以访问最新版本。打开终端输入&#xff1a;sudo apt-get update 卸载旧版本的docker 建议继续之前卸载任何旧的docker软件。打开终端输入&#xff1a;sudo apt-get remove docker docker-engine …

【Linux系统编程】:信号(2)——信号的产生

1.前言 我们会讲解五种信号产生的方式: 通过终端按键产生信号&#xff0c;比如键盘上的CtrlC。kill命令。本质上是调用kill()调用函数接口产生信号硬件异常产生信号软件条件产生信号 前两种在前一篇文章中做了介绍&#xff0c;本文介绍下面三种. 2. 调用函数产生信号 2.1 k…

专业电脑数据恢复软件 iFind Data Recovery v9.2.3 绿色便携版

前言 iFinD Data Recovery一款特别实用的数据找回工具&#xff0c;它很厉害&#xff0c;能帮你在SSD硬盘和Windows10系统上找回丢失的数据。而且&#xff0c;它还能深度扫描并恢复各种主流数码相机里的RAW格式照片&#xff0c;速度超快&#xff0c;用起来也很稳定顺畅&#xf…

QT:Widgets中的数据库应用

SQL数据库驱动 pro文件中添加如下一行代码 QT sql widgetsmain.cpp #include <QApplication> #include <QSqlDatabase> #include <QStringList> int main(int argc, char *argv[]) {QApplication a(argc, argv);qDebug() << "Available driver…