二叉树的中序遍历算法

一,简介

二叉树的中序遍历在计算机行业有着重要的作用,其中一个应用就是判断一棵二叉树是否二叉排序树。

下面介绍递归和非递归两种方式实现中序遍历。

二,递归实现

递归实现非常简单,左根右依次进行即可。

void mid_scan2(node* now)
{if(now->left != NULL)mid_scan2(now->left);cout<<now->num<<",";if(now->right != NULL)mid_scan2(now->right);
}

三,非递归实现

约定:

如果当前二叉树的某个结点没有左(右)孩子,那么该结点的左(右)孩子为NULL。

指针指向的结点,被称为当前结点。

1,实现思路

(1)如果根节点为空,则退出函数,否则将当前指针指向根节点,并进行以下的步骤:

(2)如果当前结点非空,将当前元素压栈,指针向左孩子。循环该步骤直至指针指空。

(3)如果当前指针指空,则:

                a,退栈,将指针指向退栈出来的元素,输出这个元素的数据。

                b,判断当前结点的右子树是否为空。

                       b(1) 如果非空,则指针指向当前结点的右孩子,跳转到步骤(2)

                        b(2)如果为空,退栈,将指针指向退栈出来的元素,输出这个元素的数据。

                                   b(2-2)让指针指向当前结点右子树根结点。

(4)重复执行以上操作。

2,具体代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
using namespace std;
typedef struct node0{ int num;node0* left;node0* right;
}node;void layer_scan(node* head,int n)//层次遍历 ,用来验证二叉排序树的生成是否成功 
{cout<<"层次遍历的结果:"<<endl; node* queue = (node*)malloc(sizeof(node)*(n+1));//层次遍历所需队列 int size = n+1;int i;int front=0,rear=0;//队空时,front和rear相等;队满时rear的下一个就是front//node* now = (node*)malloc(sizeof(node));queue[rear++] = *head;while(front != rear) {if(queue[front].left != NULL){queue[rear] = *(queue[front].left);rear = (rear + 1)%size;}if(queue[front].right != NULL){queue[rear] = *(queue[front].right);rear = (rear + 1)%size;}cout<<queue[front].num<<",";front = (front + 1)%size;}cout<<endl;
}int* mid_scan(node* head,int n)//中序非递归遍历,并将遍历顺序存储在数组中然后返回 
{cout<<"中序非递归遍历的结果是:"<<endl; if(head == NULL){cout<<"该树为空!"<<endl;return NULL; }int* result = (int*)malloc(sizeof(int)*(n+1));//存储结果的栈 node* stack = (node*)malloc(sizeof(node)*(n+1));//实现非递归遍历的栈 int top=0;//stack的栈顶指针 int top2=0;//result的栈顶指针 node* now;//当前指针 now = head;//初始化当前指针 while(top>=0){while(now != NULL)//当前指针非空,那么就入栈,向左子树前进 {stack[top++] = *now;now = now->left;}top--;if(top<0)return result;now = &stack[top] ;//出栈,并让当前指针指向出栈的元素 cout<<now->num<<",";result[top2++] = now->num;if(now->right != NULL)//右子树非空就往右前进一步,然后continue {now = now->right;continue;}else{top--;if(top<0)return result;now = &stack[top] ;cout<<now->num<<",";result[top2++] = now->num;now = now->right;}}return result;
}
void mid_scan2(node* now)//中序递归遍历算法 
{if(now->left != NULL)mid_scan2(now->left);cout<<now->num<<",";if(now->right != NULL)mid_scan2(now->right);
}
node* BST_tree(int n)//建立一颗二叉排序树,该二叉树的结点个数为n,结点的值是随机的.
{//中序遍历二叉排序树的结果序列是一个有序序列,该函数最后返回该二叉排序树的根结点指针 node* head;//根结点指针 node* now; int i,num;srand(time(0));//随机改变下面的随机种子 for(i=0;i<n;i++){num = rand() % (n*n);node* p = (node*)malloc(sizeof(node));p->num = num;//cout<<num<<",";if(i==0) {head = p;head->left = NULL;head->right = NULL;}now = head;while(now->left!=NULL || now->right!=NULL)//未到达叶子结点时 {if(p->num > now->num){if(now->right == NULL)break;now = now->right;}else {if(now->left == NULL)break;now = now->left;}}if(p->num > now->num)//该if-else语句用来实现新结点在当前叶子结点的插入 now->right = p;else now->left  = p;p->left = NULL;p->right = NULL;}cout<<endl;return head;//返回根结点指针 
}void question_285_06()//验证答案 
{int n,i;node* head;int* mid_serial;//接收中序非递归遍历序列 n=10;head = BST_tree(n);//生成二叉排序树 cout<<"层次遍历,验证二叉排序树,"; layer_scan( head, n);//层次遍历,验证二叉排序树的生成是 cout<<"中序递归遍历的结果是:"<<endl;mid_scan2(head);//中序递归遍历 cout<<endl;mid_serial = mid_scan( head, n);//中序非递归遍历序列 cout<<endl;cout<<"mid_serial数组中的内容是:"<<endl;for(i=0;i<n;i++)cout<< *(mid_serial+i)<<",";cout<<endl;
}
int main()
{question_285_06();return 0;
}

运行结果:

如有错误,敬请指正,礼貌交流,感激不尽 

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

二叉树中序遍历的三种方法

二叉树是一种重要的数据结构&#xff0c;对二叉树的遍历也很重要。这里简单介绍三种二叉树中序遍历的方法。二叉树的中序遍历就是首先遍历左子树&#xff0c;然后访问当前节点&#xff0c;最后遍历右子树。对于下面的二叉树&#xff0c;中序遍历结果如下&#xff1a; 结果&…

(数据结构)二叉树中序遍历

二叉树中序遍历 二叉树中序遍历的实现思想是&#xff1a; 访问当前节点的左子树访问根节点访问当前节点的右子树 图 1 二叉树 以上图 1 为例&#xff0c;中序遍历的过程如下&#xff1a; 访问该二叉树的根节点&#xff0c;找到 1遍历节点 1 的左子树&#xff0c;找到节点 2遍…

二叉树的先序、中序、后序以及层次遍历

二叉树的先序、中序、后序以及层次遍历 方法&#xff1a;在遍历二叉树的时候&#xff0c;一个节点的遍历我们把它看做要经过它三次(下图红色区域)。 当经过一次&#xff0c;被写出来的点&#xff0c;我们称它为先序遍历。 当经过两次&#xff0c;被写出来的点&#xff0c;我…

(数据结构)二叉树后序遍历

二叉树后序遍历 二叉树后序遍历的实现思想是&#xff1a; 访问当前节点的左子树访问当前节点的右子树访问根节点 图 1 二叉树 以上图 1 为例&#xff0c;后序遍历的过程如下&#xff1a; 从根节点 1 开始&#xff0c;遍历该节点的左子树&#xff08;以节点 2 为根节点&#…

二叉树的中序遍历

二叉树文章系列&#xff1a; 二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历二叉树的层序遍历二叉树的前序、中序、后序、层序遍历【解法完整版】 本文目录 一、解题思路&#xff1a;递归二、解题思路&#xff1a;迭代 二叉树的中序遍历的记忆法则是“左根右"&#x…

MySQL基础- 多表查询 和 事务

目录 多表查询多表关系多表查询概述多表查询的分类内连接外连接自连接联合查询union&#xff0c;union all子查询标量子查询列子查询行子查询表子查询 综合练习小结 事务事务简介事务的操作四大特性ACID并发事务问题事务的隔离级别小结 多表查询 之前的SQL语句里的DQL只能进行…

【C++入门】什么是引用

目录 一、引用概念 二、引用特性 三、常引用 四、使用场景 1. 做参数 2. 做返回值 五、传值&#xff0c;传引用效率比较 六、引用和指针的区别 一、引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取一个别名&#xff0c;编译器不会为引用变量开辟内存空间…

C++ 函数对象 详解

目录 &#x1f914;函数对象&#xff1a; &#x1f914;本质&#xff1a; &#x1f914;特点&#xff1a; 代码示例&#xff1a; 运行结果&#xff1a; &#x1f914; 内置函数对象&#xff1a; 1.算数仿函数 代码示例&#xff1a; 运行结果&#xff1a; 2.关系仿函数 …

华为OD机试真题B卷 Java 实现【字符串分隔】,附详细解题思路

一、题目描述 输入一个字符串&#xff0c;请按长度为8拆分每个输入字符串并进行输出&#xff0c;长度不是8整数倍的字符串请在后面补数字0&#xff0c;空字符串不处理。 二、输入描述 连续输入字符串(每个字符串长度小于等于100)。 三、输出描述 依次输出所有分割后的长度…

如何查看Steam的17位Id

方法/步骤 1、点击左上角Stream中的设置 2、 进入后点击“界面”&#xff0c;勾选“当可用时显示steam URL 地址栏”。 3、最后点击“查看个人资料”后17位即为ID。

steam注册模拟注册

代替手动模拟注册steam帐号

账号的注册

给账号注册&#xff0c;主要是给数据库中添加一个账号类数据&#xff0c;如图是以userName为用户名和password为密码的数据列表&#xff1a; 给用户和密码添加新的数据就是一个基础的账号注册&#xff0c;下面是页面的主要内容代码样式&#xff1a; 给相应的元素赋予name值&…

Steam注册遇到CAPTCHA问题,一直注册不了,一个简单的注册办法

这个问题一直解决不了 后来我就用了V.P.eN翻墙在Google Chrome上粘贴进入网址再注册就巨快 我自己用的一个很简洁&#xff0c;好用免费的VPeN叫白鲸 V.P.eN下载网址&#xff1a;https://www.bjch110.com/?mid1003 下载安装都很简单 然后白鲸显示连接上后&#xff0c;就打开Goo…

怎样注册邮箱账号?

邮箱账号的注册可以按照以下2种途径&#xff1a; 一、Web端注册 1、网页端搜索&#xff1a;http://163.net&#xff0c;点击“立即注册” 2、4个邮箱套餐&#xff0c;可以根据自己的使用情况进行选择 3、填写申请的邮箱账号&输入密码&#xff0c;手机号码&#xff0c;完…

Unity账号注册

Unity账号注册 文章目录 Unity账号注册 先找到Unity官网 看图: ##基本信息填入 &#xff1a; 密码格式&#xff1a; 用户名错误提示 用户名已存在: 用户名无效&#xff08;可能含有特殊字符或特殊字符串&#xff09;: ##验证信息 账号注册有两种验证方法&#xff1a;…

Steam注册到交易

Steam注册到交易 Steam注册到交易 Steam注册到交易Steam注册注册邮箱下载steam和网易UU加速注册Steam 手机令牌绑定 Steam注册 注册邮箱 163网易免费邮–中文邮箱第一品牌 申请一个你喜欢的邮箱名字和你的手机号就注册好你的邮箱啦。 下载steam和网易UU加速 大概是在这里…

IMX6ULL裸机篇之I2C相关寄存器

一. I2C实验 I2C时钟选择与传输速率 1. IMX6ULL的 I2C频率标准模式 100kbit/S&#xff0c;快速模式为 400Kbit/S 2. 时钟源选择 perclk_clk_rootipg_clk_root66MHz&#xff08;由之前的时钟实验章节可以知道是 66MHz&#xff09;。 二. I2C 寄存器配置 I2Cx_IFDR寄存器&…

使用docker和minio实现对象存储

文章目录 使用docker和minio实现对象存储什么是minio安装minio使用minio 使用docker和minio实现对象存储 什么是minio ​ Minio是一个开源的分布式文件存储系统&#xff0c;它基于 Golang 编写,虽然轻量&#xff0c;却拥有着不错的高性能&#xff0c;可以将图片、视频、音乐、…

k 折交叉验证

1. 原理步骤&#xff1a; 第一步&#xff0c;不重复抽样将原始数据随机分为 k 份。第二步&#xff0c;每一次挑选其中 1 份作为测试集&#xff0c;剩余 k-1 份作为训练集用于模型训练。第三步&#xff0c;重复第二步 k 次&#xff0c;这样每个子集都有一次机会作为测试集&…

R语言k折交叉验证

“机器学习中需要把数据分为训练集和测试集&#xff0c;因此如何划分训练集和测试集就成为影响模型效果的重要因素。最近我们被要求撰写关于k折交叉验证的研究报告&#xff0c;包括一些图形和统计输出。本文介绍一种常用的划分最优训练集和测试集的方法——k折交叉验证。” k折…