GD32F103RCT6/GD32F303RCT6-UCOSIII底层移植(4)消息队列实验

   本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发

       后续项目主要在下面该专栏中发布:

手把手教你嵌入式国产化_不及你的温柔的博客-CSDN博客

       感兴趣的点个关注收藏一下吧!

       电机驱动开发可以跳转:

手把手教你嵌入式国产化-实战项目-无刷电机驱动(1)-CSDN博客

       BMS电源系统开发可以跳转:暂未放链接

 向上代码兼容GD32F303RCT6中使用

本项目配套开发板:

基于GD32F103RCT6国产GD32平台,以下教程编写基于该开发板

图片:

a83f44e3ba7542238ec2f3c3d9002bbe.jpeg​​​

原理图以及例程请联系客服获取!

注意:

本教程致力于解决所有在调试中出现的所有问题,如有未包含在的问题,请联系QQ:2049363803,有奖更新文档!

参考资料:

《UCOS-III开发指南_V1.5》

《µC/OS-III Documentation》

《ARM Cortex-M3 与 Cortex-M4 权威指南(第 3 版)》

《uCOS-III内核实现与应用开发实战指南—基于STM32》

介绍

消息队列,又称为消息队列,是实时操作系统中一种重要的内核对象,它用于任务间或中断与任务间的通信,实现数据传递。消息队列的特点和工作方式灵活,支持多种通信模式,以下是其基本概念的详细解析:

 数据结构与功能:       

 消息息队列是一种数据结构,通常由一系列消息单元组成,每个单元存放一条消息。每个消息可能包含指针指向实际数据的指针、消息的大小、时间戳等元数据,以及指向下一个消息的指针,形成链表或队列。

  1. 先进先出列(FIFO) 默认情况下,消息队列遵循先进先出原则,即先加入队列的消息会被首先取出。这适用于大多数需要顺序处理消息的场景。

  2. 后进先出(LIFO) uCOS还支持后进先出(LIFO),紧急消息会排在队列头部。这种模式下,新来的消息优先被处理,适用于紧急或优先级较高的消息传递。

  3. 超时机制   在尝试读取空队列时,任务可以选择等待(阻塞),并指定超时长。超时未等到消息,任务自动恢复就绪,继续执行。

  4. 发送模式   任务或中断服务程序可以发送消息到队列。发送时,若队列未满,操作成功;满则返回错误。

  5. 资源管理   为提高效率,uCOSOSIII引入了消息池概念,预先初始化时将数组链表为链表,动态分配消息。消息池简化了消息分配与回收,减少了开销耗时开销操作。

  6. 删除    当队列不再使用,可通过API删除,资源被清理,释放关联的内存,不可再用,除非重新创建。

  7. 消息类型和长度    uCOS支持不同长度的消息,不限类型,通过指针传递,无论数据大小,处理时间复杂度一致,便于内存管理。

  8. 任务消息队列     与普通列不同,任务消息队列专属于特定任务,仅该任务可接收,其他任务发送。它不带等待列表,简化了等待处理,提高了效率。

应用场景:

  • 传感器数据处理:  在物联网应用中,传感器任务定期收集数据发送数据到处理任务,使用消息列。处理任务从列中获取数据进行分析,实现异步操作。

  • 任务间协作:  多任务合作场景,如生产者-消费者模型,生产者任务生产消息到列,消费者任务消费。列作为缓冲区,平衡任务速率差异,防止数据丢失。

  • 状态更新:   系统状态更新,如任务状态改变,如任务状态变化,通过消息列告知其他任务。这样,其他任务能即时响应状态变化,实现动态调整。

实现细节:

  • 队列控制块:每个队列在uCOSIII由控制块管理,包含队列的属性如队列的指针、消息数、入队指针、出队针等。

  • API安全性:uCOSIII提供安全API如OS_QPost、QPend等,检查错误处理,确保安全,如参数验证、中断锁调度、队列状态。

  • 中断中使用:uCOSIII允许中断中使用列操作,如中断服务例程向列发送消息,需注意配置中断安全使用,确保不破坏系统稳定性。

消息队列的阻塞机制

消息队列的阻塞机制是uCOSIII中用于解决任务间通信的同步问题的一种重要机制。该机制确保了任务在尝试访问共享资源时的竞争公平性和同步性,尤其是当资源暂时不可被任务调用时,任务能够被允许等待直至消息队列资源可用。

  1. 阻塞:当任务尝试从空列读取消息而列无消息时,可以选择进入阻塞状态。这意味着任务暂停执行,直到满足特定条件(如消息到达)才继续。

  2. 超时:任务等待时长:在阻塞时,任务可以指定超时长,即最长等待时间。若超时未收到消息,任务将自动恢复执行,任务不会继续等待,哪怕这个时候任务依旧没有等到消息队列更新。

  3. 优先级排序:如果多个任务阻塞在同一个消息队列上,此时优先级更高的任务会被调度器优先唤醒获得消息的处理权。uCOSIII根据任务优先级自动管理等待队列,有效保证了任务与任务之间从消息队列中获取消息的顺序。

  4. 模式:uCOSIII提供了不同的任务阻塞模式,比如OS_OPT_PEND用于等待,OS_OPT_NO_WAIT不等待。在实际使用中我们需要根据需求去选择不同的工作模式。

  5. 唤醒:一旦消息列存在消息更新,调度器会重新唤醒当前因消息队列阻塞而等待的任务。任务由阻塞态重新变为就绪态,此时该任务可以被调度执行。

消息队列常用函数

OSQend()

功能:用于从消息队列中获取(接收)消息。任务会等待直到消息可用(如果设置了等待选项为阻塞等待模式)或超时才继续执行。

参数

  OS_Q *p_q:指向消息队列的指针
 OS_TICK timeout:等待时长,单位为0表示无限等待;非0则为等待时长
 OS_OPTopt:操作选项,如OS_OPT_PEND_BLOCKING表示阻塞等待,OS_OPT_NO_WAIT`表示不等待
 OS_MSG_SIZE *p_msg_size:传出参数,返回消息的大小
 CPU_TS *p_ts:传出参数,消息发送时戳
 OS_ERR *p_err:传出错误代码

void *OSQPend (
OS_Q *p_q,  
// 消息队列指针
OS_TICK timeout,  
// 等待期限(单位:时钟节拍)
OS_OPT opt,  
// 选项
OS_MSG_SIZE *p_msg_size,  
// 返回消息大小(单位:字节)
CPU_TS *p_ts,  
// 获取等到消息时的时间戳
OS_ERR *p_err)
// 返回错误类型

例子:
CPU_TS ts;
OS_MSG_SIZE msg_size;
char *pMsg;
OS_ERR err;
pMsg = OSQPend(&queue, 0, OS_OPT_PEND, &msg_size, &ts, &err);
if (err == OS_ERR_NONE) {
    printf("Message received, size=%d: %d, content: %.*s\n", msg_size, msg_size, pMsg);
} else if (err == OS_ERR_PEND_TIMEOUT) {
    printf("Timeout waiting for message.\n");} else {
    printf("Error %d\n", err);}

OSQPost()

功能:向消息列发送消息。任务或中断服务程序可以将消息放入队列,如果有任务等待则唤醒它们。
参数:
OS_Q *p_q:指向消息队列的指针
void *p_void:指向消息内容的指针- OS_MSG_SIZE msg_size:消息大小- OS_OPT opt:选项,如OS_FIFO先进先出列,OS_LIFO后出列
OS_ERR *p_err:传出错误代码

void OSQPost (
OS_Q *p_q, 
// 消息队列指针
void *p_void, 
// 消息指针
OS_MSG_SIZE msg_size,
// 消息大小(单位:字节)
OS_OPT opt, 
// 选项
OS_ERR *p_err) 
// 返回错误类型

例子:
char msg[] = "Hello World!";
OS_ERR err;
OSQPost(&queue, (void *)msg, sizeof(msg), OS_FIFO, &err);
if (err == OS_ERR_NONE) {
    printf("Message sent.\n");}
else {
    printf("Error sending: %d\n", err);}

OSQDel()

功能:删除消息列。此操作永久删除队列,删除后不可再使用。确保删除前无任务等待队列。
参数:
OS_Q *p_q:指向队列的指针- OS_OPTopt:删除选项,如OS_OPT_DEL_ALWAYS总是立即删除
OS_ERR *p_err:传出错误

OS_OBJ_QTY      OSQDel (
OS_Q *p_q,   // 消息队列指针
OS_OPT opt, // 选项
OS_ERR *p_err)   // 返回错误类型

例子:
_OS_ERR err;
if (OSQDel(&queue, OS_OPT_DEL_ALWAYS, &err) == OS_ERR_NONE) {
    printf("Queue deleted.\n");}
else {
    printf("Error deleting: %d\n", err);}

OSQCreate()

功能:创建新队列。为任务间通信分配内存并初始化队列结构。
参数:
OS_Q *p_q:指向队列的指针- CPU_CHAR *name:队列名称- OS_MSG_QTY:队列大小。
OS_ERR *p_err:传出错误。

void OSQCreate (
OS_Q *p_q, 
// 消息队列指针
  CPU_CHAR *p_name, 
// 消息队列名称
OS_MSG_QTY max_qty,
// 消息队列大小(不能为 0
OS_ERR *p_err) 
// 返回错误类型

例子:
_OS_Q queue;
_OS_ERR err;
OSQCreate(&queue, "ExampleQueue", 10, &err);
if (err == OS_ERR_NONE) {
    printf("Queue created.\n");}
else {
    printf("Error creating: %d\n", err);}

消息队列实验

接下来,让我们来建立一下消息队列的实验,其中AppTaskPost()用于向队列中发送信息;AppTaskPend()用于从队列中接收信息。然后用串口打印接收到的信息。

在本次实验之前,我们还没有在系统中加入我们常用的串口调试打印的代码,那么本次开始我们将逐渐完善。

首先从之前定义的外设库中取出usart的头文件和源文件,具体的也可以参考:GD32F103RCT6/GD32F303RCT6(6.3)USART通讯实验

  

复制到User中的Bsp文件下:

  

不要忘记载入和头文件包含了:

  

  

然后初始化

  

这样我们就可以在系统中对其进行调用了!

记得关闭串口中断,我们本次实验使用不到:

  

app.c

#include <includes.h>


/*
*************************************************************************
* 任务栈存放区域
*************************************************************************
*/


static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE];

static CPU_STK AppTaskPostStk [ APP_TASK_LED1_STK_SIZE ]; 
static CPU_STK AppTaskPendStk [ APP_TASK_LED2_STK_SIZE ]; 



/*
*************************************************************************
* 定义任务控制块存放区域
*************************************************************************
*/
static OS_TCB AppTaskStartTCB;

static OS_TCB AppTaskPostTCB;
static OS_TCB AppTaskPendTCB;


/*
*************************************************************************
* 函数原型存放区域
*************************************************************************
*/

static void AppTaskStart (void *p_arg);

static void AppTaskPost ( void * p_arg ); 
static void AppTaskPend ( void * p_arg ); 


/*
*************************************************************************
* 消息队列存放区域
*************************************************************************
*/

OS_Q queue; //声明消息队列



/*
*************************************************************************
* main 函数
*************************************************************************
*/
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
	OS_ERR err;
	
	OSInit(&err);
	
	OSTaskCreate((OS_TCB *)&AppTaskStartTCB, 
							(CPU_CHAR *)"App Task Start",
							(OS_TASK_PTR ) AppTaskStart,
							(void *) 0,
							(OS_PRIO ) APP_TASK_START_PRIO,
							(CPU_STK *)&AppTaskStartStk[0],
							(CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,
							(CPU_STK_SIZE) APP_TASK_START_STK_SIZE,
							(OS_MSG_QTY ) 5u,
							(OS_TICK ) 0u,
							(void *) 0,
							(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
							(OS_ERR *)&err);
  OSStart(&err);
							
							
}


/*
*************************************************************************
* 空闲任务存放区域
*************************************************************************
*/

static void AppTaskStart (void *p_arg)
{
    CPU_INT32U cpu_clk_freq;
    CPU_INT32U cnts;
    OS_ERR err;
    
    
    (void)p_arg;
    
    BSP_Init(); /* Initialize BSP functions 
    */
    CPU_Init();
    
    cpu_clk_freq = BSP_CPU_ClkFreq(); /* Determine SysTick reference 
    freq. */
    cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz; /* Determine 
    nbr SysTick increme nts */
    OS_CPU_SysTickInit(cnts); /*Init uC/OS periodic time src(SysTick).*/
    
    
    Mem_Init(); /* Initialize Memory Management Module 
    */
    
    #if OS_CFG_STAT_TASK_EN > 0u
    OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task 
    running */
    #endif
    
    CPU_IntDisMeasMaxCurReset();
    
   		/* 创建消息队列 queue */
		OSQCreate ((OS_Q *)&queue, //指向消息队列的指针
		(CPU_CHAR *)"Queue For Test", //队列的名字
		(OS_MSG_QTY )20, //最多可存放消息的数目
		(OS_ERR *)&err); //返回错误类型
 
 
    OSTaskCreate((OS_TCB *)&AppTaskPostTCB,/*Create the Led1 task */ 
    (CPU_CHAR *)"App Task Led1", 
    (OS_TASK_PTR ) AppTaskPost, 
    (void *) 0, 
    (OS_PRIO ) APP_TASK_LED1_PRIO, 
    (CPU_STK *)&AppTaskPostStk[0], 
    (CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE / 10, 
    (CPU_STK_SIZE) APP_TASK_LED1_STK_SIZE, 
    (OS_MSG_QTY ) 5u, 
    (OS_TICK ) 0u, 
    (void *) 0, 
    (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), 
    (OS_ERR *)&err); 
    
    OSTaskCreate((OS_TCB *)&AppTaskPendTCB, /*Create the Led2 task*/ 
    (CPU_CHAR *)"App Task Led2", 
    (OS_TASK_PTR ) AppTaskPend, 
    (void *) 0, 
    (OS_PRIO ) APP_TASK_LED2_PRIO, 
    (CPU_STK *)&AppTaskPendStk[0], 
    (CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE / 10, 
    (CPU_STK_SIZE) APP_TASK_LED2_STK_SIZE, 
    (OS_MSG_QTY ) 5u, 
    (OS_TICK ) 0u, 
    (void *) 0, 
    (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), 
    (OS_ERR *)&err); 
    
    
    
    OSTaskDel ( & AppTaskStartTCB, & err ); 
    
}


 /*
 ********************************************************************
 * LED1 TASK
 ********************************************************************
 */
 
static void AppTaskPost ( void * p_arg ) 
{ 
 OS_ERR err; 

 CPU_SR_ALLOC();
 (void)p_arg; 
 
 
 while (DEF_TRUE) 
 {
	 
	 
	  char Post_test[]=" uC/OS-III test";
	 /* 发布消息到消息队列 queue */
		OSQPost ((OS_Q *)&queue, //消息变量指针
		(void *)Post_test, 
		//要发送的数据的指针,将内存块首地址通过队列“发送出去”
		(OS_MSG_SIZE )sizeof ( Post_test ),//数据字节大小
		(OS_OPT )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, 
		//先进先出和发布给全部任务的形式
		(OS_ERR *)&err); //返回错误类型
		
		if ( err == OS_ERR_NONE ) //如果接收成功
			{
			OS_CRITICAL_ENTER(); //进入临界段
			
				printf ( "\r\n 发送消息的长度:%d 字节,内容:%s\r\n", sizeof ( Post_test ), Post_test );
			
			OS_CRITICAL_EXIT();
			
			}
		
		
		OSTimeDlyHMSM ( 0, 0, 0, 500, OS_OPT_TIME_DLY, & err );
	 
 }
 
 
} 
 
 
 /*
 ***********************************************************************
 * LED2 TASK
 ************************************************************************
 */
 
static void AppTaskPend ( void * p_arg ) 
{ 
 OS_ERR err; 
 OS_MSG_SIZE msg_size;
 
 CPU_SR_ALLOC();	
 char * pMsg;
 (void)p_arg; 
 
 
 while (DEF_TRUE) 
	 { 
		 /* 请求消息队列 queue 的消息 */
			pMsg = OSQPend ((OS_Q *)&queue, //消息变量指针
			(OS_TICK )0, //等待时长为无限
			(OS_OPT )OS_OPT_PEND_BLOCKING, 
			//如果没有获取到信号量就等待
			(OS_MSG_SIZE *)&msg_size, //获取消息的字节大小
			(CPU_TS *)0, //获取任务发送时的时间戳
			(OS_ERR *)&err); //返回错误
			
			if ( err == OS_ERR_NONE ) //如果接收成功
			{
			OS_CRITICAL_ENTER(); //进入临界段
			
			printf ( "\r\n 接收消息的长度:%d 字节,内容:%s\r\n", msg_size, pMsg );
			
			OS_CRITICAL_EXIT();
			
			}
   }
}










烧录下载:

  

完成实验!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java | Leetcode Java题解之第109题有序链表转换二叉搜索树

题目&#xff1a; 题解&#xff1a; class Solution {ListNode globalHead;public TreeNode sortedListToBST(ListNode head) {globalHead head;int length getLength(head);return buildTree(0, length - 1);}public int getLength(ListNode head) {int ret 0;while (head…

kimi :系统框架 实力学习

学海无涯&#xff0c;你&#xff0c;准备好了吗&#xff1f; 学习一个新的嵌入式系统架构&#xff0c;你"只"需要 - 1 - 手册/速查函数&#xff08;对于比较大的架构&#xff0c;F12往往返回多个结果&#xff0c;增加混乱&#xff09;&#xff1b; 2 - 源代码和VS&am…

20.有序性与内存屏障

文章目录 有序性与内存屏障1.重排序1.1.编译器重排序1.2.CPU重排序1.2.1.指令级重排序1.2.2.内存系统重排序1.3.As-if-Serial规则 2.内存屏障2.1.硬件层面的内存屏障2.1.2.写屏障2.1.3.读屏障2.1.4.全屏障 2.2.硬件层的内存屏障作用2.3.案例 有序性与内存屏障 有序性 与 可见性…

混合组网VS传统网络:智能硬件混合组网优劣势浅要解析

智能硬件混合组网是一种利用多种通信技术相结合的方法&#xff0c;以实现更灵活、更可靠的网络连接。通过蓝牙、Wi-Fi、LoRa、4G相互之间的不同通讯方式&#xff0c;根据应用场景的不同以及现场实际环境&#xff0c;优选最佳物联网混合组网方案&#xff0c;以达到部署最便捷性价…

云曦2024年春季学期期中考复现

目录 Web Web_SINGIN 简简单单的文件上传 好玩的PHP 渗透的本质 简简单单的sql re baby_re easy xor Crypto easy_rsa Rsa2 Crypto_Singin Pwn pwn_Sing Misc easy_singin Xjpg 流量分析1 流量分析3 流量分析2 Web Web_SINGIN 1.使用右键检查&#xff0c…

IMU内参标定(理论)

1、内参标定标定什么&#xff1f; 生产零偏、标度因数误差、安装误差 2、现象是什么&#xff1f; 零偏现象&#xff1a;即使没有任何运动或旋转&#xff0c;IMU传感器仍然会输出一个非零的信号。零偏是一个恒定的误差&#xff0c;导致测量值始终偏离实际值。对于加速度计&am…

DolphinDB 携手九鞅科技,助力固收投研效能飞跃

随着金融市场开放的广度与深度不断拓宽&#xff0c;金融产品呈现出多样化的发展态势&#xff0c;其中债券投资组合凭借其低风险性、高流动性与稳健的收益表现&#xff0c;逐渐成为投资理财领域备受瞩目的焦点。投资经理不仅需要了解哪些债券值得投资&#xff0c;更要对债券投资…

【GESP试卷】2024年03月Scratch四级试卷

2024年GESP03月认证Scratch四级试卷 分数&#xff1a;100 题数&#xff1a;27 一、单选题(共15题&#xff0c;每题2分&#xff0c;共30分) 010203040506070809101112131415CDBBACBCDCDADBA 1、小杨的父母最近刚刚给他买了一块华为手表&#xff0c;他说手表上跑的是鸿蒙&…

朋友正确交往方式,以及保留有效沟通,才是对朋友的尊重!

人生就像一列火车&#xff0c;从生命之初驶向生命的终点&#xff0c;路途上有很多站点&#xff0c;每一个站点都会遇到不同的人&#xff0c;结交各式各样的朋友&#xff0c;中间有人下车&#xff0c;有人上车&#xff0c;有人与你走着走着就散了&#xff0c;有人偶有相见却已是…

Qt 科目一考试系统(有源码)

项目源码和资源&#xff1a;科目一考试系统: qt实现科目一考试系统 一.项目概述 该项目是一个基于Qt框架开发的在线考试系统&#xff0c;主要实现了考试题目的随机抽取、考试时间限制、成绩统计等功能。用户可以通过界面操作进行考试&#xff0c;并查看自己的考试成绩。 二.技…

计算机网络之应用层知识点总结

6.1 网络应用模型 &#xff08;1&#xff09;应用层概述 &#xff08;2&#xff09;网络应用模型的介绍 客户/服务器&#xff08;C/S&#xff09;模型 P2P模型 6.2 域名解析系统DNS &#xff08;1&#xff09;DNS系统介绍 &#xff08;2&#xff09;域名 &#xff08;3&#…

AI爆文写作:标题需要什么?情绪炸裂,态度要激烈,行为要夸张!

现在这个传播环境下&#xff0c;在公域中&#xff0c;轻声细语&#xff0c;慢慢的说&#xff0c;无法吸引到注意&#xff0c;没有人搭理。 标题要需要情绪张扬&#xff0c;态度激烈&#xff0c;行为夸张&#xff0c;大声喧闹。 唐韧的用户群是互联网产品经理&#xff0c;阅读量…

小猫咪的奇幻冒险:一个简单的Python小游戏

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、游戏简介与演示 二、游戏开发与运行 1. 环境搭建 2. 代码解析 3. 加速机制 三、游戏…

油猴插件刷学习通

油猴插件刷学习通 edge浏览器 浏览器进入这个网址https://microsoftedge.microsoft.com/addons/search/%E6%B2%B9%E7%8C%B4tampermonkey?hlzh-CN。 点我自动进入 点那个绿色的&#xff0c;点击获取 油猴插件下载在了这里 找到油猴图标&#xff0c;获取新脚本。 安装 …

DPDK实践之(1)dpdk基础使用

DPDK实践之(1)dpdk基础使用 Author: Once Day Date: 2024年5月19日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文档可参考专栏&#xff1a;Linux基础知识_Once…

Unity Terrain Adjust插件使用教程

一、Terrain Adjust插件介绍 二、插件下载以及导入 1、官方下载地址&#xff1a;Terrain Adjust 2、积分下载地址&#xff1a;Terrain Adjust 下载好之后&#xff0c;回到Unity当中&#xff0c;导入下载好之后的unitypackage包 三、插件使用 1、在使用之前一定要在场景中新…

【数据结构】二叉树的功能实现

文章目录 关于二叉树的创建如何创建二叉树实现二叉树的前、中、后序遍历层序遍历 关于二叉树的创建 在笔者的上一篇文章中堆进行了一个详细介绍&#xff0c;而二叉树是以堆为基础进行创建&#xff0c;它与堆的显著不同是 堆像是一个线性结构&#xff0c;堆的结构往往是一个数…

刷题之寻找重复数(leetcode)

寻找重复数 这题实际上就是变形的环形链表Ⅱ&#xff0c;下标为index的下一个元素是nums[index]&#xff0c;下下一个元素是nums[nums[index]] class Solution { public:int findDuplicate(vector<int>& nums) {int fast0;int slow0;while(1){fastnums[nums[fast]]…

力扣第141题和142题-环形链表,是否有环,环的入口节点

因这2道题均不改变链表结构&#xff0c;所以可以不创建新的临时头结点 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ bool hasCycle(struct ListNode *head) {if(headNULL||head->nextNULL)//若只有一个数…

Linux笔记之命令行JSON处理器jq

Linux笔记之命令行JSON处理器jq code review! 文章目录 Linux笔记之命令行JSON处理器jq1.安装2.jq 基本用法3.例程3.1. 示例JSON文件3.2. 读取特定字段3.3. 管道过滤器&#xff08;Pipe Filters&#xff09;3.4. 映射过滤器&#xff08;Map Filters&#xff09;3.5. 条件过滤…