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

问题描述:

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

示例:
二叉树:[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;一直是启动了一个真正的…

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

前言微服务在编程圈火的是不行不行的啦&#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…

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

之前的一个博客 数据结构——二叉树的层次遍历看完这个&#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;为二叉树的先序序…

.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.二叉树的所有路径 与…

台电x80plus装linux,纤巧却不简单——台电X80 Plus评测

8英寸平板一直是各平板品牌混战厮杀的大战场。“性价比”是这个尺寸平板好坏的最重要关键字。今天就为大家带来台电8英寸X80 Plus平板电脑的评测。X80 Plus是台电8英寸产品中的最新款&#xff0c;采用的是英特尔新一代CherrTrail架构芯片Atom X5 Z8300。HD核显由原来的Gen7升级…

数据结构——二叉树的递归算法

二叉树的结构定义&#xff1a; typedef struct BiNode {TElemType data;struct BiNode *lchild;struct BiNode *rchild; }BiNode,*BiTree;这里包含的递归算法有&#xff1a; 二叉树的先序创建&#xff1b;二叉树的先序中序后序遍历&#xff1b;二叉树的销毁算法&#xff1b;双…

使用BeetleX访问redis服务

BeetleX针对redis访问封了全async/await操作模式&#xff0c;通过它可以更高效地访问redis服务。BeetleX.Redis提供读写分离和多机故意写入处理&#xff0c;同时安全的TLS访问机制&#xff0c;在使用功能上组件支持绝大部分基础指令&#xff0c;并提供json&#xff0c;protobuf…

鸿蒙系统可以替代安卓吗,华为今天发布的鸿蒙系统,到底能不能替代安卓?

对于大部分差友们来说&#xff0c;“开发者大会”这个词一定显得陌生而又遥远&#xff0c;跟普通的产品发布会不一样&#xff0c;他们面向的对象并不是普通的消费者&#xff0c;而是各种程序猿和攻城狮。话又说回来&#xff0c;能开“ 开发者大会”&#xff0c;也说明这个企业已…

android loading封装_我们经常用的Loading动画居然还有这种姿势

背景Loading动画几乎每个Android App中都有。一般在需要用户等待的场景&#xff0c;显示一个Loading动画可以让用户知道App正在加载数据&#xff0c;而不是程序卡死&#xff0c;从而给用户较好的使用体验。同样的道理&#xff0c;当加载的数据为空时显示一个数据为空的视图、在…

数据结构——基于字符串模式匹配算法的病毒感染检测

实验四 基于字符串模式匹配算法的病毒感染检测 【实验目的】 1.掌握字符串的顺序存储表示方法。 2.掌握字符串模式匹配BF算法和KMP算法的实现。 【实验内容】 问题描述 医学研究者最近发现了某些新病毒,通过对这些病毒的分析,得知它们的DNA序列都是环状的。现在研究者已收集了…