【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)

目录

  • 一、二叉树剩余函数
    • 1.1二叉树的层序遍历
    • 1.2判断二叉树是否为完全二叉树
    • 1.3二叉树销毁
  • 二、二叉树的构建及遍历OJ题

一、二叉树剩余函数

1.1二叉树的层序遍历

层序遍历: 除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。 可以参考下图:
在这里插入图片描述
由上图不难看出,我们要控制函数一层一层的遍历二叉树。且普通递归都是会先遍历整个左子树,然后才会进入右子树。这里可以引用队列(先进先出)的概念,思路如下:
先将根节点地址入队列,然后利用循环,每当有节点出队列时就将此节点的左孩子(root -> left)的地址和右孩子(root -> right)的地址入队列(当然入队列的节点不为空,需要判断一下)。当队列为空时(while(!QueueEmpty(&q))),就结束循环并销毁队列。主要还是利用队列的思想,只要想到就不难,代码如下:

//二叉树层序遍历
void BinaryTreeLevelOrder(TreeNode* root)
{Queue q;QueueInit(&q);//根节点入队列if (root)QueuePush(&q, root);while (!QueueEmpty(&q)){//出队列TreeNode* front = QueueFront(&q);QueuePop(&q);printf("%d ", front->val);//左右孩子判空,并入队列if (root->left)QueuePush(&q, root->left);if (root->right)QueuePush(&q, root->right);}putchar('\n');//销毁QueueDestroy(&q);
}

代码图解:
在这里插入图片描述

1.2判断二叉树是否为完全二叉树

这里先要介绍一下两种特殊的二叉树:

  1. 满二叉树: 一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是2^k-1 则它就是满二叉树。
  2. 完全二叉树: 完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。(即如果一棵树只有右节点没有左节点,那不能成为完全二叉树)。

根据上面的介绍,不难发现如果想要判断二叉树是否为完全二叉树,还是要一层一层的遍历二叉树。 既然如此,那么此函数还是可以使用队列来实现。代码设计思路:
第一步: 同样可以先创建队列并初始化,将第一个根节点的地址先入队列。同样执行循环,将一个节点出队列时,并将此节点的左孩子地址(root->left)和右孩子地址(root->right)都入队列。不同的是如果遇到空节点(无左孩子或右孩子便是NULL)同样要进入队列,并以队列为空(while (!QueueEmpty(&q)))作为循环结束条件(事实上此循环无法通过此条件结束)。在循环内部,如果接收到的出队列的节点为空,同样结束循环(break)。
至于遇到空节点,为什么要结束循环?因为我们判断的是完全二叉树,在进行层序遍历时,不会出现两个有效节点间还有一个空节点的情况(可以参考完全二叉树结构来思考!)。
第二步: 进行队列后续节点判断,同样可以依靠循环来不断出队列节点,当队列所出的节点不是空时(front != NULL)就直接销毁队列,并返回false;如果队列遍历到最后都没有发现空节点,那么便结束循环,销毁队列并返回true

代码如下:

//判断树是否为完全二叉树
bool BinaryTreeComplete(TreeNode* root)
{Queue q;QueueInit(&q);//根节点入队列if (root)QueuePush(&q, root);while (!QueueEmpty(&q)){//队首出队列TreeNode* front = QueueFront(&q);QueuePop(&q);if (front == NULL)break;//左右孩子入队列QueuePush(&q, root->left);QueuePush(&q, root->right);}//队列遇空,判断后续节点while (!QueueEmpty(&q)){TreeNode* front = QueueFront(&q);QueuePop(&q);//当还有非空节点时说明二叉树为非完全二叉树//销毁并返回falseif (front != NULL){QueueDestroy(&q);return false;}}//直到队列为空,认为找到非空节点//销毁队列并返回trueQueueDestroy(&q);return true;
}

代码图解:
在这里插入图片描述
有关层序遍历的例题:

  1. 某二叉树的后序遍历序列与中序遍历序列相同,均为 ABCDEF ,则按层次输出(同一层从左到右)的序列(A

    A FEDCBA
    B CBAFED
    C DEFCBA
    D ABCDEF

解: 解此题首先要搞清,后序遍历和中序遍历的特性,(后序:左子树,右子树,根;中序:左子树,根,右子树),根据题目所描述的后序和中序遍历相同,那么这棵二叉树必定没有右子树。
既然这样,那么可以依据后序遍历确定根节点为F,然后依次判断以后节点。

1.3二叉树销毁

关于二叉树的销毁,可以使用后续遍历的思想。 因为如果先释放上层节点,那么下层的节点将无法寻到。如:free(root);,那么root便会变为野指针,root->left来找寻左子树也是非法的。

//二叉树的销毁
void BinaryDestroy(TreeNode* root)
{if (!root)return;BinaryTreeDesTroy(root->left);BinaryTreeDesTroy(root->right);free(root);
}

二、二叉树的构建及遍历OJ题

二叉树的构建及遍历,牛客刷题:KY11 二叉树遍历

题目描述: 编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串ABC##DE#G##F###其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

解此题首先要创建二叉树的节点(值val,指向左孩子指针left,指向右孩子指针right)。然后根据字符串arr中的数据来,连接各个节点,需要注意的是要使用前序遍历来连接。至于为什么要传pi的地址? 因为在递归过程中需要取到字符串arr不同下标位置的字符,传地址,在递归过程便可任意改变pi的值。

代码如下:

#include <stdio.h>
#include<stdlib.h>typedef char BTDataType;
//二叉树节点
typedef struct BinaryTree
{BTDataType val;struct BinaryTree* left;struct BinaryTree* right;
}BTNode;
//读取字符串,并连接二叉树各个节点
BTNode* BinaryTreeCreat(char* arr,int* pi)
{if(arr[*pi] == '#'){(*pi)++;return NULL;}BTNode* node = (BTNode*)malloc(sizeof(BTNode));if(node == NULL){perror("malloc()::fail");exit(-1);}node->val = arr[*pi];(*pi)++;node->left = BinaryTreeCreat(arr, pi);node->right = BinaryTreeCreat(arr, pi);return node;
}
//中序遍历打印
void BinaryTreeInOrder(BTNode* root)
{if(root == NULL)return;BinaryTreeInOrder(root->left);printf("%c ",root->val);BinaryTreeInOrder(root->right);
}int main() {char arr[101];scanf("%s",arr);int pi = 0;BTNode* tree = BinaryTreeCreat(arr,&pi);BinaryTreeInOrder(tree);return 0;
}

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

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

相关文章

存内生态构建重要一环- 存内计算工具链

本篇文章重点讲述存内计算相关工具链&#xff0c;我们将从工具链定义出发&#xff0c;依次讲述工具链研究背景及现有工具链、存内计算相关工具链发展现状、存内计算工具链未来展望等内容。 一.工具链研究背景及现有工具链 工具链&#xff0c;英文名称toolchain&#xff0c;通…

自然语言处理-文本标注

文本标注 现在让我们考虑词元级任务&#xff0c;比如文本标注&#xff08;text tagging&#xff09;&#xff0c;其中每个词元都被分配了一个标签。在文本标注任务中&#xff0c;词性标注为每个单词分配词性标记&#xff08;例如&#xff0c;形容词和限定词&#xff09;。 根据…

SpringBoot整合RabbitMQ实现发布订阅

RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;用于通过轻量级消息传递协议&#xff08;AMQP&#xff09;在分布式系统中传递消息。在RabbitMQ中&#xff0c;主要有以下角色&#xff1a; 生产者&#xff08;Producer&#xff09;&#xff1a;负责发送消息的应用程序。…

MySQL数据的增删改查

小练习 1. 在数据库 exercise 中创建课程表 stu_course &#xff0c;包含字段课程编号 (number) &#xff0c;类型为整数&#xff0c;长度为 11 &#xff0c;是主键&#xff0c;自增长&#xff0c;非空、课程名称 (name) &#xff0c;类型为字符串&#xff0c;长度为 20 &…

The Rise and Potential of Large Language Model Based Agents: A Survey 导读

这篇论文探讨了基于大型语言模型(LLM)的智能代理的发展和潜力。传统的AI算法或训练策略只能提高特定任务的表现,而LLM作为通用且强大的模型,可以为设计适应不同场景的智能代理提供基础。作者提出了一个包含“大脑”、“感知”和“行动”的通用框架,并将其应用于单个代理、…

oracle视图、存储过程、定时任务、用户授权、备份表

视图 create or replace view user_view as select user_id,dept_id,phonenumber,name,user_name from sys_user where del_flag0 and status0 and sfyzhY;存储过程 create or replace procedure sg_zzjg ascursor region_list isselect ID_,CODE_,CREATE_TIME,CREATE_USER_I…

macos Android平台签名证书(.keystore)

一、申请appid的使用说明&#xff08;有appid的请忽略申请apid&#xff09; 创建应用 申请的appid在源码视图填写后会自动生成一个对应的包名 ⚠️注意&#xff1a;申请appid的时候应用名称和项目名称保持一致。 二、 Android如何使用自用证书进行打包 1.找到安装jdk的路径 …

【深度学习】【AutoDL】【SSH】通过VSCode和SSH使用AutoDL服务器训练模型

身边没有显卡资源或不足以训练模型时&#xff0c;可以租赁服务器的显卡。 1、注册AutoDL并配置环境 首先打开AutoDL官网&#xff0c;注册账号并租赁自己期望的显卡资源 点击“租赁”之后&#xff0c;我们要继续选择基础环境。此处&#xff0c;我们让其自动配置好基础的pytor…

【速存】深入理解Django ORM:编写高效的数据库查询

Django作为一个高级Python Web框架&#xff0c;其自带的对象关系映射&#xff08;ORM&#xff09;是其最强大的特性之一。ORM允许开发者以编程语言原生的方式操作数据库&#xff0c;而无需编写原始的SQL查询。本文展示如何在Django项目中利用ORM执行各种数据库查询&#xff0c;…

.NET中的matplotlib平替,ScottPlot简单使用

文章目录 前言解决方案Python调用.NET 原生解决 ScottPlot找到文章ScottPlot Nuget安装简单代码测试代码跑不了5.0新版本测试 总结 前言 我之前在学OpenCV 三语言开发的时候&#xff0c;遇到了一个问题&#xff0c;怎么可视化的显示数据。Python有matplotlib&#xff0c;那么C…

Tomcat的安装及配置教程

文章目录 一、Tomcat二、安装流程三、常见问题四、相关文章 一、Tomcat Tomcat是一个开源的Java Servlet容器&#xff0c;它实现了Java Servlet和JavaServer Pages&#xff08;JSP&#xff09;规范&#xff0c;并为Java Web应用程序提供Web服务器环境。以下是Tomcat的一些详细…

量化交易学习2(因子研究)

因子有效性检验 参考1 参考2 在多因子研究框架中&#xff0c;因子的有效性检验是不可避免的工作&#xff0c;其本质是衡量一个因子的选股能力。 目前学术界和业界普遍使用的两种方法&#xff1a; 相关性检验 因子的相关性检验即检验单因子和收益率之间是否存在相关性 IC值 计…

20240126请问在ubuntu20.04.6下让GTX1080显卡让whisper工作在large模式下?

20240126请问在ubuntu20.04.6下让GTX1080显卡让whisper工作在large模式下&#xff1f; 2024/1/26 21:19 问GTX1080模式使用large该如何配置呢&#xff1f; 这个问题没有完成&#xff0c;可能需要使用使用显存更大的显卡了&#xff01; 比如GTX1080Ti 11GB&#xff0c;更猛的可…

C++(Qt)软件调试---静态分析工具clang-tidy(18)

C(Qt)软件调试—静态分析工具clang-tidy&#xff08;18&#xff09; 文章目录 C(Qt)软件调试---静态分析工具clang-tidy&#xff08;18&#xff09;1、概述2、clang-tidy基本用法3、目前已有检查项4、Qt Creator中安装clang-tidy5、Qt Creator中使用clang-tidy6、Clang-Tidy配置…

HTML5 服务器发送事件(Server-Sent Events)

前言&#xff1a; 文章内容参考&#xff1a; HTML5 服务器发送事件(Server-Sent Events) | 菜鸟教程 microsoft/fetch-event-source - npm event-source-polyfill - npm 正文&#xff1a; HTML5服务器发送事件&#xff08;server-sent event&#xff09;允许网页获得来自服务器…

websocket 通信协议

websocket是什么 答: 它是一种网络通信协议&#xff0c;是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 意思就是服务器可以主动向客户端推送信息&#xff0c;客户端也可以主动向服务器发送信息 属于服务器推送技术的一种. 为什么需要websocket? 疑问?…

Windows Server Nginx 反向代理Spring Boot配置无效 404 未找到

一个Spring Boot的系统&#xff0c;开发完成发布到Windows服务器里&#xff0c;使用nginx作为反向代理&#xff0c;修改刷新配置文件&#xff0c;nginx.conf&#xff0c;总是报错404。 这个是不生效刷新配置文件的bat脚本&#xff1a; REM 切换到NGINX安装目录 cd D:\nginx-1.…

修复WordPress内部服务器错误的步骤及解决方案

WordPress是一款广泛使用的开源内容管理系统&#xff0c;但在使用过程中&#xff0c;可能会遇到各种内部服务器错误。这些错误可能由于多种原因引起&#xff0c;例如插件冲突、文件权限问题、服务器配置不当等。为了帮助您快速解决这些问题&#xff0c;本文将为您提供一套详细的…

数据结构排序算详解(动态图+代码描述)

目录 1、直接插入排序&#xff08;升序&#xff09; 2、希尔排序&#xff08;升序&#xff09; 3、选择排序&#xff08;升序&#xff09; 方式一&#xff08;一个指针&#xff09; 方式二&#xff08;两个指针&#xff09; 4、堆排序&#xff08;升序&#xff09; 5、冒…

Golang协程池ants使用笔记

最近工程中遇到goroutine滥用导致的bug&#xff0c;采用了ants协程池来解决。 github-ants官方源码和使用说明。 记录一个例子 package mainimport ("fmt""runtime""github.com/panjf2000/ants/v2" )// 模拟一个任务&#xff1a;求数字x的平方 …