【数据结构】二叉树的非递归遍历(完整代码)

article/2025/9/22 15:58:03

默认给一棵树前序遍历的结果,按要求创建这棵树(#表示空),并用非递归的方法对它进行遍历。

解题思路

1.递归遍历: 则将二叉树的遍历看作是分治问题,将每一棵树都分为根-左子树-右子树三部分,每部分按同样的方法递归遍历即可。具体实现见下篇博客 二叉树的实现&递归遍历
2.非递归遍历:我们可以借用栈的知识完成树的遍历。使用栈完成的过程以下面的前序遍历为例

前序: 根–> 左–> 右
主要思路:若根节点有效则输出并入栈;访问其左子树遇到根节点输出并入栈直到根节点下再无左子树,将栈顶元素出栈,并继续访问它的右子树;直至栈内无元素且当前元素无效,遍历结束。
具体过程如下:

1.根节点A有效则输出并入栈,访问A左树(输出条件:当前根节点有效;也是入栈条件)
2.B有效则输出并入栈,访问B左树
3.D有效则输出并入栈,访问D左树
4.D左树为空,当前栈顶D出栈,访问D右树(出栈条件:左树/右树 为空,栈顶元素出栈)
5.D右树为空,当前栈顶B出栈,访问B右树
6.E有效则输出并入栈,访问E左树
7.E左树为空,当前栈顶E出栈,访问E右树
8.F有效则输出并入栈,访问F左树
9.F左树为空,当前栈顶F出栈,访问F右树
10.F右树为空,当前栈顶A出栈,访问A右树
11.C有效则输出并入栈,访问C左树
12.C左树为空,当前栈顶C出栈,访问C右树
13.C右树为空,栈内无元素 (结束条件:栈内无元素,或者当前元素为空)
遍历结束!!

在这里插入图片描述

实现前序的代码如下所示:

//前序:A  B  D  E  F  C
while (StackEmpty(&st) != 0 || cur != NULL)  //循环条件:与(栈内无元素,或者当前元素为空)相反
{while (cur != NULL)  //输出/入栈条件:当前节点不为空{printf("%c ", cur->_data);  //输出StackPush(&st, cur);  //入栈cur = cur->_left;  //访问节点左子树}BTNode* top = StackTop(&st);  //找到栈顶元素StackPop(&st);   /出栈条件:左树/右树 为空,栈顶元素出栈cur = top->_right;  //访问右子树
}

中序: 左 --> 根 --> 右

//中序:D  B  E  F  A  C
while (StackEmpty(&st) != 0 || cur != NULL) //当栈不为空或当前节点有效,循环继续{while (cur != NULL)  //当前节点不为空{StackPush(&st, cur); //节点入栈cur = cur->_left;  //访问左子树}BTNode* top = StackTop(&st);  //找到栈顶元素printf("%c ", top->_data);  //输出栈顶元素StackPop(&st);  //栈顶元素出栈cur = top->_right;  //访问右子树}

后序: 左 --> 右 --> 根
注意:要判断此时访问的结点之前是否访问过!!

//后序:D  F  E  B  C  A
BTNode* prev = NULL;
while (cur || StackEmpty(&st) != 0){while (cur != NULL){StackPush(&st, cur);  //入栈cur = cur->_left;  //访问左子树}BTNode* top = StackTop(&st);if (top->_right == NULL || top->_right == prev) //右子树为空,或者已经访问过{StackPop(&st);  //栈顶元素出栈printf("%c ", top->_data); //输出prev = top;}else cur = top->_right;}

完整代码

BT.h – 头文件
#define _CRT_SECURE_NO_WARNINGS 1
#ifndef __TREE_H__
#define __TREE_H__ #include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>typedef char BTDataType;
typedef struct BinaryTreeNode   //树节点定义
{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;
}BTNode;//创建树
BTNode *BinaryTreeCreate(BTDataType*a, int*pi);
//销毁树
void BinaryTreeDestory(BTNode* root);
//非递归遍历
void BinaryPrevOrder(BTNode* root);  //前序
void BinaryInOrder(BTNode* root);   //中序
void BinaryPostOrder(BTNode* root);   //后序
//测试类
void Test();typedef BTNode* STDataType;
typedef struct Stack   //栈定义
{STDataType* _a;int _top;int _capacity;
}Stack;//栈的操作
void StackInit(Stack* ps);  //初始化
void StackDestory(Stack* ps);  //销毁
void StackPush(Stack *ps, STDataType x);  //入栈
void StackPop(Stack* ps);  //出栈
STDataType  StackTop(Stack* ps);  //取栈顶元素
int StackEmpty(Stack* ps); //判断栈空
int StackSize(Stack* ps);  //判断栈内元素
void StackPrint(Stack* ps);   //栈节点输出#endif//__TREE_H__
BT.c – 树的操作
#define _CRT_SECURE_NO_WARNINGS 1
#include "BT.h"BTNode *BinaryTreeCreate(BTDataType*a, int* pi)  //创建树
{if (a[*pi] == '#'){(*pi)++;return NULL;}BTNode* root = (BTNode*)malloc(sizeof(BTNode));root->_left = root->_right = NULL;root->_data = a[*pi];(*pi)++;root->_left = BinaryTreeCreate(a, pi);root->_right = BinaryTreeCreate(a, pi);return root;
}void BinaryTreeDestory(BTNode* root)  //销毁树
{if (root){BinaryTreeDestory(root->_left);BinaryTreeDestory(root->_right);free(root);root = NULL;}
}void BinaryPrevOrder(BTNode* root)  //前序遍历
{Stack st;StackInit(&st);BTNode* cur = root;while (StackEmpty(&st) != 0 || cur != NULL){while (cur != NULL){printf("%c ", cur->_data);StackPush(&st, cur);cur = cur->_left;}BTNode* top = StackTop(&st);StackPop(&st);cur = top->_right;}
}void BinaryInOrder(BTNode* root)  //中序遍历
{Stack st;StackInit(&st);BTNode* cur = root;while (StackEmpty(&st) != 0 || cur != NULL){while (cur != NULL){StackPush(&st, cur);cur = cur->_left;}BTNode* top = StackTop(&st);printf("%c ", top->_data);StackPop(&st);cur = top->_right;}
}void BinaryPostOrder(BTNode* root)  //后序遍历
{BTNode* cur = root;BTNode* prev = NULL;Stack st;StackInit(&st);while (cur || StackEmpty(&st) != 0){while (cur != NULL){StackPush(&st, cur);cur = cur->_left;}BTNode* top = StackTop(&st);if (top->_right == NULL || top->_right == prev){StackPop(&st);printf("%c ", top->_data);prev = top;}else cur = top->_right;}
}void Test()  //测试
{char a[20] = "ABD##E#H##CF##G##";int pi = 0;int i = 0;BTNode* root = BinaryTreeCreate(a, &pi);printf("树创建成功!\n");printf("树前序遍历的结果是: ");BinaryPrevOrder(root);printf("\n");printf("树中序遍历的结果是: ");BinaryInOrder(root);printf("\n");printf("树后序遍历的结果是: ");BinaryPostOrder(root);printf("\n");BinaryTreeDestory(root);printf("销毁成功!\n");
}

ST.c – 栈的操作

#define _CRT_SECURE_NO_WARNINGS 1
#include "BT.h"void StackInit(Stack* ps)  //栈的初始化
{assert(ps);ps->_a = NULL;ps->_capacity = 0;ps->_top = 0;
}void StackDestory(Stack* ps)  //栈的销毁
{assert(ps);ps->_capacity = 0;ps->_top = 0;free(ps->_a);ps->_a = NULL;
}void StackPush(Stack *ps, STDataType x)  //入栈
{assert(ps);if (ps->_top == ps->_capacity){size_t newcapacity = (ps->_capacity == 0 ? 4 : ps->_capacity * 2);ps->_a = (STDataType*)realloc(ps->_a, sizeof(STDataType)*newcapacity);ps->_capacity = newcapacity;}ps->_a[ps->_top] = x;ps->_top++;
}void StackPop(Stack* ps)  //出栈
{assert(ps&&ps->_top>0);ps->_top--;
}STDataType  StackTop(Stack* ps)  //取栈顶元素
{assert(ps&&ps->_top>0);return ps->_a[ps->_top - 1];
}int StackEmpty(Stack* ps)  //判断栈是否为空
{assert(ps);if (ps->_top == 0)return 0;else return 1;
}int StackSize(Stack* ps)  //判断栈内元素
{assert(ps);STDataType size = ps->_top;return size;
}void StackPrint(Stack* ps)  //输出栈内元素
{assert(ps);while (StackEmpty(ps) != 0){printf("%d ", StackTop(ps));StackPop(ps);}printf("\n");
}
main.c – 主文件
#define _CRT_SECURE_NO_WARNINGS 1
#include "BT.h"int main()
{printf("      *******二叉树的实现******\n");Test();printf("\n");system("pause");return 0;
}

http://chatgpt.dhexx.cn/article/sn3QBmUw.shtml

相关文章

数据结构--二叉树的遍历(非递归)

我们已经对二叉树的基本概念有了一定的了解&#xff0c;也对它的递归版本的前、中、后序遍历掌握的很好了&#xff0c;那么接下来就要介绍二叉树中遍历的非递归版本 >【数据结构】二叉树详解< 先看本篇文章效果更佳哦 目录 1、非递归遍历解析2、前序遍历(非递归)3、中序…

二叉树的非递归遍历 C语言版

文章作者&#xff1a;Slyar 文章来源&#xff1a;Slyar Home (www.slyar.com) 转载请注明&#xff0c;谢谢合作。 上周数据结构课在讲二叉树的遍历&#xff0c;老师只讲递归算法&#xff0c;没有什么技术含量&#xff0c;遂自己琢磨非递归算法实现... 前序遍历:先访问根节点&…

二叉树非递归遍历

1. 遍历一棵树 前、中、后序遍历的路径实际是相同的&#xff0c;都是以如上路径去游历。 前、中、后序访问的结果不同&#xff0c;实际是访问节点的时机不同&#xff1a; 前序&#xff1a;一遇到节点就去访问 中序&#xff1a;访问完左树再去访问 后序&#xff1a;访问完右子…

C语言数据结构七:二叉树非递归遍历

二叉树的非递归遍历&#xff0c;必须借助栈的辅助。必须采用栈的这种先进后出的特性。 算法实现思路&#xff1a; 我们先将根节点压入栈中。然后往外弹出元素。直到栈中元素弹完为止。1、将根节点压入栈中。&#xff08;但是压入栈中&#xff0c;并不知简单的将根节点压入栈中…

二叉树非递归遍历(先序、中序、后序)

首先是一个二叉树结构&#xff1a; class TreeNode{public int value;public TreeNode left;public TreeNode right;public TreeNode(){}public TreeNode(int v){valuev;} 非递归的二叉树遍历需要用到栈的先进后出。 先序遍历 步骤&#xff1a; 1、首先定义一个当前正在检索…

二叉树非递归遍历(c语言)

结果如下图&#xff1a; #号代表NULL&#xff0c;此时没有节点 一、在c语言中进行二叉树的非递归遍历需要用到栈&#xff0c;而在c语言中没有直接调用栈的接口&#xff0c;所以在实现非递归遍历时需要先实现一个栈&#xff0c;需要用到出栈&#xff0c;入栈&#xff0c;栈顶元…

二叉树非递归遍历实现(Java)

首先理解一下二叉树节点结构。left指向左节点&#xff0c;right指向右节点&#xff0c;val为节点中的值。 class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int x) {val x;}} 先序遍历 //非递归先序遍历&#xff08;需一个辅助栈&#xff0c;顺序为根…

二叉树遍历的一些非递归算法

二叉树的非递归算法因为涉及到栈和队列&#xff0c;所以写的时候总是受到伪代码的干扰&#xff0c;要完整的补全栈和队列的结构有些麻烦&#xff0c;这里借鉴了一些大佬的思想&#xff0c;发现可以直接在树中模拟栈和队列的存在&#xff0c;这给非递归的完整代码带来了很大的便…

三种非递归遍历二叉树的方法

就以这个树为例&#xff0c;来讲讲二叉树的非递归遍历。 先序遍历&#xff1a; 先序遍历结果为3 4 6 5 8 9&#xff0c;就拿树的左枝为例&#xff0c;3是根&#xff0c;打印&#xff0c;4是3的左孩子&#xff0c;打印&#xff0c;6是4的左孩子&#xff0c;打印&#xff0c;6的…

二叉树的非递归遍历

目录 一.前序遍历&#xff08;根左右&#xff09; 1.思路图解 2.代码 二.中序遍历&#xff08;左根右&#xff09; 1.思路图解 2.代码 三.后序遍历&#xff08;左右根&#xff09; 1.思路图解 2.代码 四.层序遍历 1.思路图解 2.代码 一.前序遍历&#xff08;根左右…

smile——Java机器学习引擎

介绍 Smile&#xff08;统计机器智能和学习引擎&#xff09;是一个基于Java和Scala的快速、全面的机器学习、NLP、线性代数、图形、插值和可视化系统。 凭借先进的数据结构和算法&#xff0c;Smile提供了最先进的性能。Smile有很好的文档记录&#xff0c;请查看项目网站以获取…

Java机器学习库(Java ML)(一、分类)

本文章翻译至Java ML技术文档classification.pdf&#xff0c;代码部分是参考该文档使用IDEA编写&#xff0c;同时加入了运行结果。 分类 本文介绍与分类相关的功能。 该文章假设您已熟悉Java ML的基础知识&#xff0c;如入门教程中所述&#xff08;http://java-ml.sourcefor…

目前流行的、强大的基于Java的机器学习开发库精选

图片来源: Mindfire Solutions 现如今&#xff0c;拥有深度学习和机器学习领域的技术是科技界的趋势之一&#xff0c;并且企业则希望雇佣一些拥有良好的机器学习知识背景的程序开发工程师。本文将介绍一些目前流行的、强大的基于Java的机器学习库&#xff0c;希望给大家带来帮助…

JAVA 人工神经网络实现,机器学习,人工智能

人工智能&#xff08;AI&#xff09; 、机器学习&#xff08;ML&#xff09;、深度学习&#xff08;DL&#xff09;、神经网络&#xff08;CNN&#xff09; IT技术圈的人怼这些词汇大家都一定耳熟能详了&#xff0c;可能圈外的也不陌生&#xff0c;但是作为一个作为一个“攻城…

机器学习java_如何开始使用Java机器学习

机器学习java 什么是开始使用Java机器学习的最佳工具&#xff1f; 他们已经存在了一段时间&#xff0c;但如今看来&#xff0c;每个人都在谈论人工智能和机器学习。 对于科学家和研究人员而言&#xff0c;它已经不再是秘密&#xff0c;几乎可以在任何新兴技术中实现。 在下面…

谁说搞Java的不能玩机器学习?

简介 机器学习在全球范围内越来越受欢迎和使用。 它已经彻底改变了某些应用程序的构建方式&#xff0c;并且可能会继续成为我们日常生活中一个巨大的&#xff08;并且正在增加的&#xff09;部分。没有什么包装且机器学习并不简单。 它对许多人来说似乎非常复杂并常常令人生畏…

基于 Java 机器学习自学笔记 (第51-53天:kNN)

注意&#xff1a;本篇为50天后的Java自学笔记扩充&#xff0c;内容不再是基础数据结构内容而是机器学习中的各种经典算法。这部分博客更侧重与笔记以方便自己的理解&#xff0c;自我知识的输出明显减少&#xff0c;若有错误欢迎指正&#xff01; 目录 一、关于数据集及其导入…

基于 Java 机器学习自学笔记 (第66至68天:主动学习之ALEC)

注意&#xff1a;本篇为50天后的Java自学笔记扩充&#xff0c;内容不再是基础数据结构内容而是机器学习中的各种经典算法。这部分博客更侧重于笔记以方便自己的理解&#xff0c;自我知识的输出明显减少&#xff0c;若有错误欢迎指正&#xff01; 目录 前言 一、关于学习的分类…

超全!基于Java的机器学习项目、环境、库...

https://yq.aliyun.com/articles/278837?utm_sourcetuicool&utm_mediumreferral 摘要&#xff1a; 你是一名希望开始或者正在学习机器学习的Java程序员吗&#xff1f; 利用机器学习编写程序是最佳的学习方式。你可以从头开始编写算法&#xff0c;但是利用现有的开源库&am…

结合Java和机器学习技术,如何驾驭大数据提升业务效率和竞争力?

随着大数据的不断增长和发展&#xff0c;越来越多的企业和组织开始关注如何利用大数据来提高业务效率和竞争力。在大数据分析领域&#xff0c;Java和机器学习技术是两个非常重要的方向。本文将介绍这两个技术的基本概念、应用场景和发展趋势&#xff0c;并重点探讨如何结合Java…