数据结构——二叉树的层次遍历

问题描述:

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。

示例:
二叉树:[3,9,20,null,null,15,7]
在这里插入图片描述

返回其层次遍历结果:

[
[3],
[9,20],
[15,7]
]
通过

来源:力扣(LeetCode)
二叉树的层序遍历

目录

1.非递归用循环队列
2.递归实现层次遍历

在栈与队列:匹配问题都是栈的强项中提到,「递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中」,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。

知识前提:循环队列,二叉树的基本运算

非递归用循环队列

//思路
进行层次遍历时构建一个辅助队列,先将二叉树根节点入队,然后出队,访问出队结点,若它有左子树,将左子树根节点入队,然后出队,访问出队结点…,右子树也同样如此,循环往复直到队列为空

1.构建好辅助队列Q和二叉树T;
2.首先将二叉树的T(根节点)入队列;
3.进入while循环,退出条件 :队列为空;
4.循环内部:首先将队列中的队首元素出栈,并且输出他的值;
若队首元素(刚刚出队的元素)有左子树,将其左子树入队
若队首元素(刚刚出队的元素)有右子树,将其右子树入队
详细代码(可直接运行)

补充:如何让输出为一层一行

方法说起来很简单,只要仔细想,应该都能想出这种方法来。

定义两个变量curLevelCount和nextLevelCount来分别保存当前层和下一层的结点数。

显然,curLevelCount的初始值为1,因为只有一个根结点,而nextLevelCount由于未知,故置为0.

思路:
1.输出一行一行的与之前输出为一行的代码大体相似
2.构建好辅助队列Q和二叉树T;
3.再定义两个变量:curLevelCount用于记录当前层次结点个数,nextLevelCount用于记录当前层次的下一层结点的个数
4.将二叉树的根节点入栈,同时curLevelCount=1,nextLevelCount=0;
5.进入while循环,退出条件 :队列为空;
6.循环内部:首先将队列中的队首元素出栈,并且输出他的值;(与此同时,将curLevelCount–);
若队首元素(刚刚出队的元素)有左子树,将其左子树入队.(与此同时,将nextLevelCount++);
若队首元素(刚刚出队的元素)有右子树,将其右子树入队.(与此同时,将nextLevelCount++);
若curLevelCount减到零:输出一个换行符,将nextLevelCount赋值给curLevelCount,
nextLevelCount=0;

代码:非递归用循环队列

#include<stdio.h>typedef int Status;
#define TRUE  1
#define FALSE 0
#define  ERROR 0
#define  OK 1
#include<malloc.h> 
#include<stdlib.h>
#include<stdio.h>
#include<bits/stdc++.h> typedef char TElemType;
typedef int status; 
typedef struct BiNode
{TElemType data;struct BiNode *lchild;struct BiNode *rchild;
}BiNode,*BiTree;
typedef BiTree ElemType;
typedef BiTree QElemType;
//----------循环队列 --顺序存储结构-----------------------
#define  MAXQSIZE  100    // 最大队列长度+1
typedef  struct {ElemType   *base;   // 初始化的动态分配存储空间int   front;    // 头指针,若队列不空,指向队列头元素int   rear;   // 尾指针,若队列不空,指向队列尾元素的下一个位置
}  SqQueue;
void InitQueue(SqQueue &Q)
{    // 构造一个空队列QQ.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));if(!Q.base) // 存储分配失败exit(0);Q.front = Q.rear = 0;
}
void DestroyQueue(SqQueue &Q)
{   // 销毁队列Q,Q不再存在if(Q.base)free(Q.base);Q.base = NULL;Q.front = Q.rear = 0;
}
int QueueLength(SqQueue &Q)
{return ((Q.rear-Q.front+MAXQSIZE)%MAXQSIZE);
}
Status EnQueue(SqQueue &Q, QElemType e)
{   // 插入元素e为Q的新的队尾元素if((Q.rear + 1) % MAXQSIZE == Q.front) // 队列满return ERROR;Q.base[Q.rear] = e;Q.rear = (Q.rear + 1) % MAXQSIZE;return OK;
}
Status DeQueue(SqQueue &Q, QElemType &e)
{  // 若队列不空,则删除Q的队头元素,用e返回其值,// 并返回OK;否则返回ERRORif(Q.front == Q.rear) // 队列空return ERROR;e = Q.base[Q.front];Q.front = (Q.front + 1) % MAXQSIZE;return OK;
}
Status GetHead(SqQueue Q, QElemType &e)
{   // 若队列不空,则用e返回Q的队头元素,并返回OK;// 否则返回ERRORif(Q.front == Q.rear) // 队列空return ERROR;e = Q.base[Q.front];return OK;
}
Status QueueEmpty(SqQueue Q)
{// 若队列Q为空队列,则返回TRUE;否则返回FALSEif(Q.front == Q.rear) // 队列空的标志return TRUE;elsereturn FALSE;
}
void traverse(SqQueue &Q)
{int x;x=Q.front;int num=QueueLength(Q);for(int i=0;i<num;i++){printf("%d--",Q.base[(x++)%MAXQSIZE]);}
}void CreateBiTree(BiTree &T)//二叉树的先序创建 
{TElemType ch;scanf("%c",&ch);if(ch=='#')T=NULL;else {T=(BiNode*)malloc(sizeof(BiNode));if(!T)exit(-1);T->data=ch;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}
}void DestroyBiTree(BiTree &T)//二叉树的销毁算法 
{if(T==NULL)exit(-1);else{DestroyBiTree(T->lchild);DestroyBiTree(T->rchild);free(T);}
}int  preorderTraverse(BiTree T)//二叉树的先序递归遍历算法 
{if(T==NULL)return 0;else {printf("%c ",T->data);preorderTraverse(T->lchild);preorderTraverse(T->rchild);}} int  InorderTraverse(BiTree T)//二叉树的中序递归遍历算法 
{if(T==NULL)return 0;else {InorderTraverse(T->lchild);printf("%c ",T->data);InorderTraverse(T->rchild);}}int  PostorderTraverse(BiTree T)//二叉树的后序递归遍历算法 
{if(T==NULL)return 0;else {PostorderTraverse(T->lchild);PostorderTraverse(T->rchild);printf("%c ",T->data);}}void BiTree_level_traversal1(BiTree T)//按层输出一行 
{SqQueue Q;InitQueue(Q);EnQueue(Q,T);BiTree temp;while(!QueueEmpty(Q)){DeQueue(Q, temp);printf("%c ",temp->data);if(temp->lchild!=NULL)EnQueue(Q,temp->lchild);if(temp->rchild!=NULL)EnQueue(Q,temp->rchild);}} void BiTree_level_traversal(BiTree T)// 层次遍历输入一层一层的 
{SqQueue Q;InitQueue(Q);EnQueue(Q,T);BiTree temp;int curLevelCount=1,nextLevelCount=0; while(!QueueEmpty(Q)){DeQueue(Q, temp);printf("%c ",temp->data);curLevelCount--;if(temp->lchild!=NULL){EnQueue(Q,temp->lchild);nextLevelCount++;}if(temp->rchild!=NULL){EnQueue(Q,temp->rchild);nextLevelCount++;}if(curLevelCount==0){printf("\n"); curLevelCount = nextLevelCount;nextLevelCount=0;}}} int main()
{BiTree T;printf("创建树输入树T的先序序列(其中使用#代表空节点)\n");CreateBiTree(T);printf("先序遍历算法");preorderTraverse(T);printf("\n中序遍历算法");InorderTraverse(T);printf("\n后序遍历算法");PostorderTraverse(T);printf("\n遍历结果为:\n");BiTree_level_traversal1(T);printf("\n一层一层的输出\n"); BiTree_level_traversal(T);
}

在这里插入图片描述

递归实现层次遍历

思路:
1.先利用BiTree_height1(BiTree T)求二叉树高度算法,求得高度
2.levelOrder( BiTree T)层次遍历递归算法(这个函数仅一个for循环),用for()将二叉树一层一层的输出,每一层输出完,再输出一个换行符。
3.printNodeAtLevel(BiTree T,int level)(真正的递归遍历输出函数)
若level==0,输入此时的T->data;

 
int BiTree_height1(BiTree T)//求树的深度算法1 
{if(T==NULL)return 0;else{if(BiTree_height1(T->lchild)>BiTree_height1(T->rchild))return 1+BiTree_height1(T->lchild);elsereturn 1+BiTree_height1(T->rchild);}} 
void printNodeAtLevel(BiTree T,int level)  
{  if(T==NULL||level<0)  return;  if(level==0)  {  printf("%c ",T->data);return;  }  // 左子树的 level - 1 级  printNodeAtLevel(T->lchild,level-1);  // 右子树的 level - 1 级  printNodeAtLevel(T->rchild,level-1);  
}void levelOrder(const BiTree T)
{if(T==NULL)return;int totalLevel = BiTree_height1(T);for(int i = 0; i< totalLevel; i++){printNodeAtLevel(T, i);printf("\n");//打印完一层,换行}
} 

代码:递归实现(全部代码)

#include<stdio.h>
#include<bits/stdc++.h> typedef char TElemType;
typedef int status; 
typedef struct BiNode
{TElemType data;struct BiNode *lchild;struct BiNode *rchild;
}BiNode,*BiTree;
void CreateBiTree(BiTree &T)//二叉树的先序创建 
{TElemType ch;scanf("%c",&ch);if(ch=='#')T=NULL;else {T=(BiNode*)malloc(sizeof(BiNode));if(!T)exit(-1);T->data=ch;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}
}void DestroyBiTree(BiTree &T)//二叉树的销毁算法 
{if(T==NULL)exit(-1);else{DestroyBiTree(T->lchild);DestroyBiTree(T->rchild);free(T);}
}int  preorderTraverse(BiTree T)//二叉树的先序递归遍历算法 
{if(T==NULL)return 0;else {printf("%c ",T->data);preorderTraverse(T->lchild);preorderTraverse(T->rchild);}} int  InorderTraverse(BiTree T)//二叉树的中序递归遍历算法 
{if(T==NULL)return 0;else {InorderTraverse(T->lchild);printf("%c ",T->data);InorderTraverse(T->rchild);}}int  PostorderTraverse(BiTree T)//二叉树的后序递归遍历算法 
{if(T==NULL)return 0;else {PostorderTraverse(T->lchild);PostorderTraverse(T->rchild);printf("%c ",T->data);}}int BiTree_height1(BiTree T)//求树的深度算法1 
{if(T==NULL)return 0;else{if(BiTree_height1(T->lchild)>BiTree_height1(T->rchild))return 1+BiTree_height1(T->lchild);elsereturn 1+BiTree_height1(T->rchild);}} 
void printNodeAtLevel(BiTree T,int level)  
{  if(T==NULL||level<0)  return;  if(level==0)  {  printf("%c ",T->data);return;  }  // 左子树的 level - 1 级  printNodeAtLevel(T->lchild,level-1);  // 右子树的 level - 1 级  printNodeAtLevel(T->rchild,level-1);  
}void levelOrder(const BiTree T)
{if(T==NULL)return;int totalLevel = BiTree_height1(T);for(int i = 0; i< totalLevel; i++){printNodeAtLevel(T, i);printf("\n");//打印完一层,换行}
} int main()
{BiTree T;printf("创建树输入树T的先序序列(其中使用#代表空节点)\n");CreateBiTree(T);printf("先序遍历算法");preorderTraverse(T);printf("\n中序遍历算法");InorderTraverse(T);printf("\n后序遍历算法");PostorderTraverse(T);printf("\n二叉树层次遍历算法\n");levelOrder(T);} 

在这里插入图片描述

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

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

相关文章

asp.net core 使用 TestServer 来做集成测试

asp.net core 使用 TestServer 来做集成测试Intro之前我的项目里的集成测试是随机一个端口&#xff0c;每次都真实的启动一个 WebServer&#xff0c;之前也有看到过微软文档上 TestServer 的介绍&#xff0c;当时没仔细看过以为差不多就没用&#xff0c;一直是启动了一个真正的…

python os system_python中os. popen system的区别

python调用Shell脚本或者是调用系统命令&#xff0c;有两种方法&#xff1a; os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码&#xff0c;正确会返回0&#xff0c;错误会返回其他数字。 后者的返回值是脚本执行过程中的输出内容。实际使用时视需求情况而选择。 p…

android 文件 c语言 jni,Android jni 调用的so文件一个函数的反汇编 高手来看看

[Asm] 纯文本查看 复制代码var_104 -0x104var_A0 -0xA0var_48 -0x48var_34 -0x34var_2C -0x2Cvar_28 -0x28STMFD SP!, {R4-R11,LR}LDR R8, (_GLOBAL_OFFSET_TABLE_ - 0x2B34)LDR R11, (__stack_chk_guard_ptr - 0xA104)SUB SP, SP, #0xE4ADD R8, PC, R8LDR R3, [R8,R11]ADD R4,…

数据结构——交换左右子树

递归——层次遍历—交换左右子树算法 思路&#xff1a; 与先序递归遍历类似 1如果有子树&#xff0c;交换这个节点的左右子树&#xff08;和交换两个变量的值一样&#xff09; 2再递归这个节点的左子树&#xff0c;右子树&#xff1b; #include<stdio.h> #include<b…

python人工智能面试题_人工智能面试题分享(含答案)

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 1、深度学习框架TensorFlow中有哪四种常用交叉熵&#xff1f; 答&#xff1a; tf.nn.weighted_cross_entropy_with_logits tf.nn.sigmoid_cross_entropy_with_logits tf.nn.softmax_cross_entropy_with_logits tf.nn.sparse_softm…

微服务很香--麻辣味,但要慢慢消化

前言微服务在编程圈火的是不行不行的啦&#xff0c;可能还有很多小伙伴还没有进行微服务实操&#xff0c;但这个词&#xff0c;要说没听过、没看过&#xff0c;那小伙伴一定是假Programmer。虽然微服务很火&#xff0c;但不能盲目使用&#xff1b;先不说涉及技术和工具有多少&a…

c语言实现灰度图像阈值分割,灰度图像--图像分割 阈值处理之平均阈值

学习DIP第52天转载请标明本文出处&#xff1a;http://blog.csdn.net/tonyshengtan &#xff0c;出于尊重文章作者的劳动&#xff0c;转载请标明出处&#xff01;文章代码已托管&#xff0c;欢迎共同开发&#xff1a;https://github.com/Tony-Tan/DIPpro开篇空话好久没写博客了&…

数据结构——二叉树的双序遍历

设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结 点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树 思路&#xff1a; 1.双序遍历与中序遍历类似&#xff0c;是中序遍历的变形 2.中序遍历是指对于二叉树的每一…

python如何封装成可调用的库_Python实现打包成库供别的模块调用

1.创建python项目bricewulib2.新建test_package包并创建info1类以及print_hello方法3.为了让包的结构再复杂点&#xff0c;我们再在test_package下面新建一个test_package2包并创建Info2类以及print_hello2方法&#xff08;注意&#xff1a;这里是Info2&#xff0c;不是上面的I…

从零开始实现 ASP.NET Core MVC 的插件式开发(九) - 如何启用预编译视图

标题&#xff1a;从零开始实现 ASP.NET Core MVC 的插件式开发(九) - 升级.NET 5及启用预编译视图作者&#xff1a;Lamond Lu地址&#xff1a;https://www.cnblogs.com/lwqlun/p/13992077.html源代码&#xff1a;https://github.com/lamondlu/Mystique适用版本&#xff1a;.NET…

android arp工具,GitHub - SummerSnow274/ARP_sed_rev: 在Android通过ARP询问实现获取同一网络所有设备的MAC地址,AP隔离的网络除外...

ARP_sed_rev在Android通过ARP询问实现获取同一网络所有设备的MAC地址&#xff0c;AP隔离的网络除外arpsed.c编译&#xff1a;gcc arpsed.c -o arpsed运行&#xff1a;sudo ./arpsed ens33 192.168.1.123 //ens33是网卡名&#xff0c;参数放在外面易于操作交叉编译在Android上运…

数据结构——二叉树的层次遍历进阶

之前的一个博客 数据结构——二叉树的层次遍历看完这个&#xff0c;可以简单实现下面的问题 问题&#xff1a; 1.计算二叉树的最大宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值。 2.用按层次顺序遍历二叉树的方法,统计树中具有度为1的结点数目。 解决问题的思路…

future.cancel不能关闭线程_多线程与高并发笔记

1. 创建线程的四种方式实现Runnable 重写run方法继承Thread 重写run方法线程池创建 Executors.newCachedThreadPool()实现Callable接口2. Thread线程操作方法当前线程睡眠指定mills毫秒Thread.sleep([mills])当前线程优雅让出执行权Thread.yield()例如Thread t1, t2&#xff0c…

ANDROID手表怎么设置壁纸,表盘背景随心换 果壳智能手表换壁纸教程

在智能手机和电脑上&#xff0c;我们一般都会换一张自己喜欢的图片作为壁纸&#xff0c;当我们想把一张喜欢的图片做成果壳GEAK Watch表盘时&#xff0c;应该怎么做呢&#xff1f;其实只要简单的几个步骤&#xff0c;你就能获得独一无二的专属表盘。首先&#xff0c;打开一张你…

如何踢掉 sql 语句中的尾巴,我用 C# 苦思了五种办法

一&#xff1a;背景 1. 讲故事这几天都在修复bug真的太忙了&#xff0c;期间也遇到了一个挺有趣bug&#xff0c;和大家分享一下&#xff0c;这是一块sql挺复杂的报表相关业务&#xff0c;不知道哪一位大佬在错综复杂的 嵌套 平行 if判断中sql拼接在某些UI组合下出问题了&#…

数据结构——二叉树的最长路径问题

题目&#xff1a; 求任意二叉树中第一条最长的路径长度,并输出此路径上各结点的值。 描述 设二叉树中每个结点的元素均为一个字符&#xff0c;按先序遍历的顺序建立二叉链表&#xff0c;编写算法求出该二叉树中第一条最长的路径。 输入 一行数据&#xff0c;为二叉树的先序序…

android http请求缓存,Android Http请求和响应使用协议缓冲区

我对协议缓冲区主题非常陌生.但我知道json解析等等现在,我实际上正在此协议缓冲区上工作,我正在制作一个使用带有协议缓冲区的android进行Http请求和响应的应用程序.我正在使用android中的协议缓冲区制作一个登录页面.服务中的一切正常工作墙返回了我想要的每个字段的响应,但是…

.NET 应用如何优雅的做功能开关(Feature Flag)

点击上方蓝字关注“汪宇杰博客”导语曾经&#xff0c;我们要在应用程序里做功能开关&#xff0c;就避免不了在配置文件里加上一堆 bool 类型的配置项&#xff0c;然后在代码里用 if else 去判断。尽管这种做法是可行的&#xff0c;但我们现在有办法让代码更加整洁&#xff0c;避…

鼠标右键 移动选定的文件夹到指定位置_iRightMouse:一款免费Mac鼠标右键增强神器...

如果你是多年的Windows用户转到macOS平台&#xff0c;你必定会发现Windows上很多非常方便的鼠标右键菜单在macOS上都是没有的&#xff0c;例如新建txt文档、一键隐藏文件等。而这些快捷功能的缺失也确实会带来一些不便&#xff0c;奇客君发现一款刚刚上线的免费右键增强工具&am…

数据结构——从叶子结点到根节点的全部路径

问题 给定一个二叉树&#xff0c;返回所有从根节点到叶子节点的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode-cn.com/problems/binary-tree-paths 257.二叉树的所有路径 与…