【数据结构】树与二叉树(十一):二叉树的层次遍历(算法LevelOrder)

news2025/3/9 10:00:40

文章目录

5.2.1 二叉树

  二叉树是一种常见的树状数据结构,它由结点的有限集合组成。一个二叉树要么是空集,被称为空二叉树,要么由一个根结点和两棵不相交的子树组成,分别称为左子树右子树。每个结点最多有两个子结点,分别称为左子结点和右子结点。
在这里插入图片描述

二叉树性质

引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i0

引理5.2:高度为k的二叉树中至多有 2 k + 1 − 1 2^{k+1}-1 2k+11个结点,其中 k ≥ 0 k \geq 0 k0

引理5.3:设T是由n个结点构成的二叉树,其中叶结点个数为 n 0 n_0 n0,度数为2的结点个数为 n 2 n_2 n2,则有 n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1

  • 详细证明过程见前文:【数据结构】树与二叉树(三):二叉树的定义、特点、性质及相关证明

满二叉树、完全二叉树定义、特点及相关证明

  • 详细证明过程见前文:【数据结构】树与二叉树(四):满二叉树、完全二叉树及其性质

5.2.2 二叉树顺序存储

  二叉树的顺序存储是指将二叉树中所有结点按层次顺序存放在一块地址连续的存储空间中,详见:
【数据结构】树与二叉树(五):二叉树的顺序存储(初始化,插入结点,获取父节点、左右子节点等)

5.2.3 二叉树链接存储

  二叉树的链接存储系指二叉树诸结点被随机存放在内存空间中,结点之间的关系用指针说明。在链式存储中,每个二叉树结点都包含三个域:数据域(Data)、左指针域(Left)和右指针域(Right),用于存储结点的信息和指向子结点的指针,详见:
【数据结构】树与二叉树(六):二叉树的链式存储

5.2.4 二叉树的遍历

  • 遍历(Traversal)是对二叉树中所有节点按照一定顺序进行访问的过程。
  • 通过遍历,可以访问树中的每个节点,并按照特定的顺序对它们进行处理。
  • 对二叉树的一次完整遍历,可给出树中结点的一种线性排序。
    • 在二叉树中,常用的遍历方式有三种:先序遍历中序遍历后序遍历
    • 这三种遍历方式都可以递归地进行,它们的区别在于节点的访问顺序
      • 在实现遍历算法时,需要考虑递归终止条件和递归调用的顺序。
    • 还可以使用迭代的方式来实现遍历算法,使用栈或队列等数据结构来辅助实现。
  • 遍历是二叉树中基础而重要的操作,它为其他许多操作提供了基础,如搜索、插入、删除等。
    在这里插入图片描述

1-3 先序、中序、后序遍历递归实现及相关练习

【数据结构】树与二叉树(七):二叉树的遍历(先序、中序、后序及其C语言实现)

4. 中序遍历非递归

【数据结构】树与二叉树(八):二叉树的中序遍历(非递归算法NIO)

5. 后序遍历非递归

【数据结构】树与二叉树(九):二叉树的后序遍历(非递归算法NPO)

6. 先序遍历非递归

【数据结构】树与二叉树(十):二叉树的先序遍历(非递归算法NPO)

7. 层次遍历

  层次遍历按层数由小到大,即从第0层开始逐层向下,同层中由左到右的次序访问二叉树的所有结点。

a. 算法LevelOrder

在这里插入图片描述

b. 算法解读

  1. 创建一个队列Q。
  2. 将指针p指向二叉树T的根节点。
  3. 如果p不为空,则将p入队列Q。
  4. 当队列Q非空时,执行以下操作:
    • 将队首元素p出队列。
    • 打印p的数据。
    • 如果p的左子节点不为空,则将左子节点入队列Q。
    • 如果p的右子节点不为空,则将右子节点入队列Q。

  使用队列来保存待访问的节点,保证按层次遍历的顺序进行访问。首先将根节点入队列,然后通过循环,每次从队列中取出一个节点,访问该节点的数据,并将其左右子节点(如果存在)依次入队列。这样就可以按照层次遍历的顺序逐层访问二叉树的节点。

c. 时间复杂度

  这个算法的时间复杂度是O(n),其中n是二叉树中节点的数量。因为每个节点都会入队列一次,出队列一次,所以总的入队和出队操作次数为2n,所以时间复杂度为O(n)。

d.代码实现

levelOrder
void levelOrder(struct Node* root) {
    if (root == NULL) {
        return;
    }

    struct Queue* front, * rear;
    create(&front, &rear);
    enqueue(&front, &rear, root);

    while (front != NULL) {
        struct Node* current = front->node;
        printf("%c ", current->data);

        if (current->left != NULL) {
            enqueue(&front, &rear, current->left);
        }
        if (current->right != NULL) {
            enqueue(&front, &rear, current->right);
        }

        dequeue(&front);
    }
}

其中,队列操作详解:【数据结构】线性表(九)队列:链式队列及其基本操作(初始化、判空、入队、出队、存取队首元素)

create
// 初始化队列
void create(struct Queue** front, struct Queue** rear) {
    *front = *rear = NULL;
}
enqueue
// 入队列
void enqueue(struct Queue** front, struct Queue** rear, struct Node* node) {
    struct Queue* temp = (struct Queue*)malloc(sizeof(struct Queue));
    if (temp == NULL) {
        printf("Memory allocation failed!\n");
        exit(1);
    }
    temp->node = node;
    temp->next = NULL;
    if (*rear == NULL) {
        *front = *rear = temp;
        return;
    }
    (*rear)->next = temp;
    *rear = temp;
}
dequeue
// 出队列
void dequeue(struct Queue** front) {
    if (*front == NULL) {
        return;
    }
    struct Queue* temp = *front;
    *front = (*front)->next;
    free(temp);
}

8. 代码整合

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

// 二叉树结点的定义
struct Node {
    char data;
    struct Node* left;
    struct Node* right;
};

// 创建新结点
struct Node* createNode(char data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        exit(1);
    }
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// 创建队列
struct Queue {
    struct Node* node;
    struct Queue* next;
};

// 初始化队列
void create(struct Queue** front, struct Queue** rear) {
    *front = *rear = NULL;
}

// 入队列
void enqueue(struct Queue** front, struct Queue** rear, struct Node* node) {
    struct Queue* temp = (struct Queue*)malloc(sizeof(struct Queue));
    if (temp == NULL) {
        printf("Memory allocation failed!\n");
        exit(1);
    }
    temp->node = node;
    temp->next = NULL;
    if (*rear == NULL) {
        *front = *rear = temp;
        return;
    }
    (*rear)->next = temp;
    *rear = temp;
}

// 出队列
void dequeue(struct Queue** front) {
    if (*front == NULL) {
        return;
    }
    struct Queue* temp = *front;
    *front = (*front)->next;
    free(temp);
}

// 层次遍历二叉树
void levelOrder(struct Node* root) {
    if (root == NULL) {
        return;
    }

    struct Queue* front, * rear;
    create(&front, &rear);
    enqueue(&front, &rear, root);

    while (front != NULL) {
        struct Node* current = front->node;
        printf("%c ", current->data);

        if (current->left != NULL) {
            enqueue(&front, &rear, current->left);
        }
        if (current->right != NULL) {
            enqueue(&front, &rear, current->right);
        }

        dequeue(&front);
    }
}

int main() {
    // 创建一棵二叉树
    struct Node* root = createNode('a');
    root->left = createNode('b');
    root->right = createNode('c');
    root->left->left = createNode('d');
    root->left->right = createNode('e');
    root->left->right->left = createNode('f');
    root->left->right->right = createNode('g');

    // 层次遍历二叉树
    printf("层次遍历二叉树: \n");
    levelOrder(root);
    printf("\n");

    return 0;
}

在这里插入图片描述

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

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

相关文章

redux-devtools谷歌扩展插件的使用示例

目录 1. store.ts 2. reducer.ts 3. ReduxProvider.tsx 4. mapStateToProps.ts 5. mapDispatchToProps.ts 6. Todo组件(最外层包ReduxProvider 7. Todo组件里面涉及的子组件 1) TodoInput.tsx 2) TodoList.tsx 3) TodoItem.tsx 8. App组件使用Todo组件 1. store.ts …

讯飞录音笔误删除WAV录音文件恢复成功案例

讯飞录音笔删除恢复的难点 难点一&#xff0c;电脑无法识别为普通电脑盘符。这个是厂家系统设计上的问题&#xff0c;本博文不涉及。 难点二&#xff0c;一般恢复后播放有间隙性噪音问题。这个是数据碎片问题&#xff0c;是本博文的关注点。 大多数情况下&#xff0c;讯飞录…

AlGaN/GaN HFET 五参数模型

标题&#xff1a;A Five-Parameter Model of the AlGaN/GaN HFET 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;15年&#xff09; 摘要—我们引入了AlGaN/GaN异质结场效应晶体管&#xff08;HFET&#xff09;漏极电流Id&#xff08;Vgs&#xff0c;Vds…

Android——Gradle插件gradle-wrapper.properties

一、Android Studio版本&#xff0c;Android Gradle插件版本&#xff0c;Gradle版本 Android Studio 通过Android Gradle插件 使用 Gradle来构建代码&#xff1b; Android Studio每次升级后&#xff0c; Android Gradle 插件自动更新&#xff0c;对应的Gradle版本也会变动&…

wsl [Ubuntu20.04.6] 安装 Hadoop

文章目录 1.安装WSL2.安装Java安装Hadoop3.3配置文件1.修改hadoop-env.sh2.修改core-site.xml3.修改hdfs-site.xml ssh启动 1.安装WSL 重启电脑 管理员打开powershell PS C:\windows\system32> wsl --list --online PS C:\windows\system32> wsl --install -d Ubuntu-2…

Linux技能篇-yum源搭建(本地源和公网源)

文章目录 前言一、yum源是什么&#xff1f;二、使用镜像搭建本地yum源1.搭建临时仓库第一步&#xff1a;挂载系统ios镜像到虚拟机第二步&#xff1a;在操作系统中挂载镜像第三步&#xff1a;修改yum源配置文件 2.搭建本地仓库第一步&#xff1a;搭建临时yum源来安装httpd并做文…

什么是Amazon Simple Email Service(SES 群发邮件)

Amazon Simple Email Service&#xff08;Amazon SES&#xff09;让您可以使用 Amazon SES API 或 SMTP 接口放心地联络到客户&#xff0c;而无需使用本地简单邮件传输协议&#xff08;Simple Mail Transfer Protocol&#xff0c;SMTP&#xff09;电子邮件服务器。 目录 什么是…

[头歌]第1关:动态学生信息管理

题目&#xff1a; C 面向对象 _ STL 的应用 (educoder.net) 考点&#xff1a; 1.自定义排序 bool cmp 2.如何使用find和erase来找到学生类里面的指定姓名的人并将其从动态数组中删除。 3.find要找的是学生类里面的成员变量而非单纯的直接找值&#xff0c;应如何实现 &…

计算机毕业设计 基于SpringBoot的驾校管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

【GIT】git分支命令,使用分支场景介绍git标签介绍,git标签命令,git标签使用的场景git查看提交历史

目录 一&#xff0c;git分支命令&#xff0c;使用分支场景介绍 二&#xff0c;git标签介绍&#xff0c;git标签命令&#xff0c;git标签使用的场景 三&#xff0c;git查看提交历史 前言&#xff1a; 今天我们来聊聊关于Git 分支管理。几乎每一种版本控制系统都以某种形式支持…

两数之和问题

题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任意顺…

Leetcode—9.回文数【简单】

2023每日刷题&#xff08;二十六&#xff09; Leetcode—9.回文数 直接法实现代码 bool isPalindrome(int x) {int len 0;int arr[10] {0};int i 0;if(x < 0) {return false;}while(x) {arr[i] x % 10;x / 10;len; }for(i 0; i < len / 2; i) {if(arr[i] ! arr[le…

如何正确使用GPT工具

引言 在快速发展的数字时代&#xff0c;人工智能&#xff08;AI&#xff09;已成为科研领域的一个不可或缺的工具。特别是像ChatGPT这样的AI聊天机器人&#xff0c;它通过高效的语言模型和深度学习算法&#xff0c;为科研工作者提供了前所未有的辅助。从文献搜索到数据分析&…

一文了解游戏行业(数据分析)

一.概况 1.基本术语 游戏行业基础术语——持续更新ing... 2.产业链 包括游戏开发&#xff0c;发行和销售等环节 游戏开发&#xff1a;上游环节&#xff1b;是游戏产业链的核心环节&#xff0c;包括游戏策划&#xff0c;美术设计&#xff0c;程序开发等&#xff0c;是决定游…

Day27力扣打卡

打卡记录 情侣牵手&#xff08;并查集&#xff09; 链接 class Solution:def minSwapsCouples(self, row: List[int]) -> int:def find(x: int) -> int:if p[x] ! x:p[x] find(p[x])return p[x]n len(row) >> 1p list(range(n))for i in range(0, len(row), 2…

【多线程 - 01、概述】

进程 几乎所有的操作系统都支持进程概念&#xff0c;进程是处于运行过程中的程序&#xff0c;进程是操作系统中进行资源分配的基本单位。 三个基本特征 独立性&#xff1a;指进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位。而对于未建立任何进程的程序&…

[PHP]Kodexplorer可道云 v4.47

KodExplorer可道云&#xff0c;原名芒果云&#xff0c;是基于Web技术的私有云和在线文件管理系统&#xff0c;由上海岱牧网络有限公司开发&#xff0c;发布于2012年6月。致力于为用户提供安全可控、可靠易用、高扩展性的私有云解决方案。 用户只需通过简单环境搭建&#xff0c;…

玩了个锤子游戏小程序搭建流程:探索深度与逻辑的结合

随着移动互联网的普及&#xff0c;小程序已经成为了越来越多用户的选择。在这个背景下&#xff0c;玩了个锤子游戏小程序应运而生&#xff0c;它为用户提供了一个全新的游戏体验。那么&#xff0c;如何搭建这样一个小程序呢&#xff1f;本文将为大家详细介绍玩了个锤子游戏小程…

数据库 关系数据理论

问题 数据冗余更新异常插入异常删除异常 一个好的模式应当不会发生插入异常、删除异常和更新异常&#xff0c;数据冗余应尽可能少 数据依赖 定义&#xff1a;一个关系内部属性与属性之间的一种约束关系&#xff08;该约束关系是通过属性间值的相等与否体现出来数据间相关联…

Goland报错:Cannot resolve symbol ‘XXX‘。一键解决该问题。

Goland报错&#xff1a;Cannot resolve symbol XXX。一键解决该问题。 问题是&#xff1a;Cannot resolve symbol XXX解决方法是&#xff1a; 问题是&#xff1a;Cannot resolve symbol ‘XXX’ 问题的背景&#xff1a; 我写了两个包&#xff0c;分别是main 、utils包。main包…