草庐IT

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

天月御奈 2024-01-02 原文

        层序遍历的作用是将二叉树,从上到下,从左到右依次遍历。如下图遍历的结果是A->B->C->D->E->F->G->H。其实,这就相当于族谱一样,从辈分大到小遍历(从祖宗到孙子)狗头保命。

 那么,该如何实现呢,接下来我们运用队列的知识,用入队列,出队列的方式来解决。

目录

1.思路

2.具体实现

(1)准备步骤

(2)队列源码(Queue.h   和    Queue.c)

(3)层序遍历实现

(4)层序遍历源码

1.思路

(1)将A入队列

(2)判断队列是否为空,不为空就将A出队列,再将A的”孩子“入队列。

 (3)判空,将B出队列,将B的“孩子”入队列。

(4)判空,将C出队列,将C的“孩子”入队列。

 (5)判空,将D出队列,将D的“孩子”入队列(“孩子”为空则不进队列)

 。。。。。。。。(步骤同理)

(6)最后,队列为空结束遍历。

2.具体实现

(1)准备步骤

因为c语言不像c++一样有队列的库函数,所以就需要我们自己来实现一个队列。下面我给大家写了一个队列(才,才不是为了给你们用的呢.傲娇脸)。

(2)队列源码(Queue.h   和    Queue.c)

下面只有层序遍历要使用到的函数(绝对不是因为懒.jpg)

Queue.h

注意, 头文件一定要包含#include”tree.h",包含二叉树的“tree.h"以免下面定义队列元素出错(下面,会写"tree.h"文件的先不要着急。

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

#include"tree.h"//包含二叉树的“tree.h"以免下面定义队列元素出错

typedef BTNode* Type;//定义队列中元素类型为二叉树节点类型

typedef struct QueueNode
{
	struct QueueNode* next;
	Type data;
}Qnode;

typedef struct Queue
{
	Qnode* head;
	Qnode* tail;
	int size;
}Queue;

//初始化
void Queue_init(Queue* pq);
//入队列
void Queue_push(Queue* pq, Type x);
//出队列
void Queue_pop(Queue* pq);
//取队首
Type Queue_front(Queue* pq);
//判空
bool Queue_empty(Queue* pq);

 Queue.c

#include"Queue.h"

//初始化
void Queue_init(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
//入队列
void Queue_push(Queue* pq, Type x)
{
	assert(pq);
	Qnode* newNode = (Qnode*)malloc(sizeof(Qnode));
	if (newNode == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	newNode->data = x;
	newNode->next = NULL;
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newNode;
	}
	else
	{
		pq->tail->next = newNode;
		pq->tail = newNode;
	}
	pq->size++;
}
//出队列
void Queue_pop(Queue* pq)
{
	assert(pq);
	assert(!Queue_empty(pq));
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		Qnode* del = pq->head;
		pq->head = pq->head->next;
		free(del);
		del = NULL;
	}
	pq->size--;
}
//队首
Type Queue_front(Queue* pq)
{
	assert(pq);
	assert(!Queue_empty(pq));
	return pq->head->data;
}

//判空
bool Queue_empty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL && pq->tail == NULL;
}

(3)层序遍历实现

tree.h

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

typedef char TreeType;

typedef struct BinaryTreeNode
{
	TreeType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* TreeCreate();
// 二叉树销毁
void TreeDestory(BTNode* root);
// 层序遍历
void TreeLevelOrder(BTNode* root);

tree.c

注意,这里也一定要有#include“Queue.h",否则队列就无法正常使用。

我用了最粗暴的创建方法(让人见了直呼好家伙)

#include"tree.h"
#include"Queue.h"

//构建二叉树 (最粗暴的创建方法)
BTNode* TreeCreate()
{
	BTNode* nA = (BTNode*)malloc(sizeof(BTNode));
	assert(nA);
	BTNode* nB = (BTNode*)malloc(sizeof(BTNode));
	assert(nB);
	BTNode* nC = (BTNode*)malloc(sizeof(BTNode));
	assert(nC);
	BTNode* nD = (BTNode*)malloc(sizeof(BTNode));
	assert(nD);
	BTNode* nE = (BTNode*)malloc(sizeof(BTNode));
	assert(nE);
	BTNode* nF = (BTNode*)malloc(sizeof(BTNode));
	assert(nF);
	BTNode* nG = (BTNode*)malloc(sizeof(BTNode));
	assert(nG);
	BTNode* nH = (BTNode*)malloc(sizeof(BTNode));
	assert(nH);

	nA->data = 'A';
	nB->data = 'B';
	nC->data = 'C';
	nD->data = 'D';
	nE->data = 'E';
	nF->data = 'F';
	nG->data = 'G';
	nH->data = 'H';

	nA->left = nB;
	nA->right = nC;
	nB->left = nD;
	nB->right = nE;
	nC->left = nF;
	nC->right = nG;
	nD->left = NULL;
	nD->right = NULL;
	nE->left = NULL;
	nE->right = nH;
	nF->left = NULL;
	nF->right = NULL;
	nG->left = NULL;
	nG->right = NULL;
	nH->left = NULL;
	nH->right = NULL;

	return nA;
}

// 二叉树销毁
void TreeDestory(BTNode* root)
{
	if (root == NULL)
		return;
	TreeDestory(root->left);
	TreeDestory(root->right);
	free(root);
}


// 层序遍历
void TreeLevelOrder(BTNode* root)
{
	Queue q;
	Queue_init(&q);
	if (root != NULL)
		Queue_push(&q, root);
	while (!Queue_empty(&q))//判空
	{
		BTNode* front = Queue_front(&q);//让front保存要出队列的节点
		Queue_pop(&q);
		printf("%c ", front->data);

		//下一层入队列(”孩子“入队列)
		if (front->left)
			Queue_push(&q, front->left);
		if (front->right)
			Queue_push(&q, front->right);
	}
}

(4)层序遍历源码

// 层序遍历
void TreeLevelOrder(BTNode* root)
{
	Queue q;
	Queue_init(&q);
	if (root != NULL)
		Queue_push(&q, root);
	while (!Queue_empty(&q))
	{
		BTNode* front = Queue_front(&q);
		Queue_pop(&q);
		printf("%c ", front->data);

		//下一层入队列
		if (front->left)
			Queue_push(&q, front->left);
		if (front->right)
			Queue_push(&q, front->right);
	}
}

 我的杀手皇后已经摸过了这篇文章了,当我按下按钮时,这篇文章将会爆炸。所以,还不快逃!!!!!☠️☠️☠️☠️

有关二叉树层序遍历(c语言,非递归)的更多相关文章

  1. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  4. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  5. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  6. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  7. ruby - Chef Ruby 遍历 .erb 模板文件中的属性 - 2

    所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP

  8. ruby - 如何遍历 Ruby 中所有正则表达式匹配的字符串? - 2

    我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby​​-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/

  9. ruby - 递归地将所有数字字符串转换为 Ruby 哈希中的整数 - 2

    我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj

  10. Ruby:标准递归模式 - 2

    我经常迷上ruby​​的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情

随机推荐