FreeRTOS之动态创建任务与删除任务

news2024/11/25 20:27:01

1.本文是利用FreeRTOS来动态创建任务和删除任务。主要是使用FreeRTOS的两个API函数:xTaskCreate()和vTaskDelete()。

任务1和任务2是让LED0、LED1闪烁。任务3是当按键按下时删除任务1。

使用动态创建任务时,需要动态的堆中申请任务所需的内存空间,所以首先需要将FreeRTOS.h中的宏定义(configSUPPORT_DYNAMIC_ALLOCATION)设置为1。

使用vTaskDelete()时需要将如下宏定义设置为1:

2.xTaskCreate()函数的6个参数参数说明:

任务优先级对应的数值越大,其优先级越高。任务句柄是相当于任务的身份证(ID),以方便其他函数通过任务句柄对其进行操作,比如vTaskDelete()中传入的任务句柄,即为删除任务句柄所对应的任务。

3.vTaskDelete()函数的参数说明:

当传入的参数为NULL,表述删除当前正在运行的任务。

4.代码:

(1)main.c:

#include "stm32f10x.h"
#include "led.h"
//#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
#include "sys.h"

//¶¨Òåstart_taskµÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 64
TaskHandle_t start_handler;
void start_task(void);

//¶¨ÒåÈÎÎñ1µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define LED0_TASK_PRIO 2
#define LED0_TASK_STACK_SIZE 64
TaskHandle_t led0_handler;
void led0(void);

//¶¨ÒåÈÎÎñ2µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define LED1_TASK_PRIO 3
#define LED1_TASK_STACK_SIZE 64
TaskHandle_t led1_handler;
void led1(void);

//¶¨ÒåÈÎÎñ2µÄÅäÖã¬ÈÎÎñ¾ä±ú£¬ÈÎÎñÓÅÏȼ¶£¬¶ÑÕ»´óС£¬ÈÎÎñÉùÃ÷£º
#define KEY_TASK_PRIO 4
#define KEY_TASK_STACK_SIZE 64
TaskHandle_t key_handler;
void key_task(void);

int flag = 0;

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é2
	LED_Init();
	KEY_Init();
	
	xTaskCreate((TaskFunction_t) start_task,																//ÈÎÎñº¯Êý
							(const char *)"start_task",																	//ÈÎÎñÃû³Æ
							(uint16_t)START_TASK_STACK_SIZE,											      //ÈÎÎñ¶ÑÕ»´óС
							(void *)NULL,																								//´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
							(UBaseType_t)START_TASK_PRIO,																//ÈÎÎñÓÅÏȼ¶
							(TaskHandle_t *)&start_handler);														//ÈÎÎñ¾ä±ú
	
			
	vTaskStartScheduler();																								//¿ªÊ¼ÈÎÎñµ÷¶È
}

/*´´½¨¿ªÊ¼ÈÎÎñ£º*/
void start_task(void)
{
//	taskENTER_CRITICAL();	
	/*´´½¨ÈÎÎñ*/
	if(flag == 0)
	{
		xTaskCreate((TaskFunction_t) led0,																		//ÈÎÎñº¯Êý
							(const char *)"led0_task",																//ÈÎÎñÃû³Æ
							(uint16_t)LED0_TASK_STACK_SIZE,											      //ÈÎÎñ¶ÑÕ»´óС
							(void *)NULL,																							//´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
							(UBaseType_t)LED0_TASK_PRIO,															//ÈÎÎñÓÅÏȼ¶
								(TaskHandle_t *)&led0_handler);														//ÈÎÎñ¾ä±ú
		xTaskCreate((TaskFunction_t) led1,
								(const char *)"led1_task",
								(uint16_t)LED1_TASK_STACK_SIZE,
								(void *)NULL,
								(UBaseType_t)LED1_TASK_PRIO,
								(TaskHandle_t *)&led1_handler);
		xTaskCreate((TaskFunction_t) key_task,
								(const char *)"key_task",
								(uint16_t)KEY_TASK_STACK_SIZE,
								(void *)NULL,
								(UBaseType_t)KEY_TASK_PRIO,
								(TaskHandle_t *)&key_handler);
	 flag = 1;
	}
	 vTaskDelay(500);
										
	 vTaskDelete(NULL);											//ɾ³ýµ±Ç°ÈÎÎñ
//	 taskEXIT_CRITICAL();
}

void led0(void)
{
	while(1)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_8);			//´ò¿ªLED
		vTaskDelay(500);
		//delay_ms(500);
		GPIO_SetBits(GPIOA,GPIO_Pin_8);			//´ò¿ªLED
		vTaskDelay(500);
	}
}

void led1(void)
{
	while(1)
	{
		GPIO_ResetBits(GPIOD,GPIO_Pin_2);			//´ò¿ªLED
		vTaskDelay(500);
		//delay_ms(500);
		GPIO_SetBits(GPIOD,GPIO_Pin_2);			//´ò¿ªLED
		vTaskDelay(500);
	}
}

/*´´½¨°´¼üÈÎÎñ£º*/
void key_task(void)
{
	uint8_t key = 0;
    while(1)
    {
        //printf("task3ÕýÔÚÔËÐУ¡£¡£¡\r\n");
        //key = KEY_Scan(0);
        if(KEY_0 == 0)
        {
            if(led0_handler != NULL)
            {
                //printf("ɾ³ýtask1ÈÎÎñ\r\n");
                vTaskDelete(led0_handler);
                led0_handler = NULL;
            }

        }
        vTaskDelay(10);
    }
}

(2)led.c和led.h:

#include "key.h"
#include "delay.h"
#include "led.h"

void KEY_Init(void)
{
	/*1.¶¨ÒåÒý½ÅµÄ½á¹¹Ìå¡£
	  2.ʹÄÜÒý½Å¶ÔÓ¦µÄʱÖÓ¡£
	  3.ÅäÖÃÒý½ÅÐÅÏ¢*/
	
	//¶¨ÒåÒý½Å½á¹¹Ì壺
	GPIO_InitTypeDef GPIO_InitStruct;
	
	//ʹÄÜʱÖÓ£º
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC,ENABLE);
	
	//ÅäÖÃÒý½ÅÐÅÏ¢(KEY0)£º
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	
	//ÅäÖÃKEY1£º
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //ÉèÖóÉÉÏÀ­ÊäÈë

	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//ÅäÖð´¼üWK_UP:
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
}

void KEY_Scan(void)
{
	static u8 key_up = 1;				//°´¼üËÉ¿ª±ê־λ
	if(key_up && (KEY_0 == 0||  KEY_1  == 0|| KEY_1 == 1))
	{
		//delay_ms(10);						  //È¥¶¶¶¯
		key_up = 0;
		if(KEY_0 == 0)
		{
			GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
			GPIO_SetBits(GPIOA,GPIO_Pin_8);
			//delay_ms(1000);
		}
		else if(KEY_1 == 0)
		{
			GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
			GPIO_SetBits(GPIOD,GPIO_Pin_2);
			//delay_ms(1000);
		}
		else if(KEY_2 == 1)
		{
			GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
			GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
		}
	}
	else if(KEY_0==1&&KEY_1==1&&KEY_2==0)
	{
		key_up = 1;
	}
}

#ifndef __LED_H
#define	__LED_H

#include "stm32f10x.h"

void LED_Init(void);

#endif

(3)key.c和key.h代码:

#include "key.h"
#include "delay.h"
#include "led.h"

void KEY_Init(void)
{
	/*1.¶¨ÒåÒý½ÅµÄ½á¹¹Ìå¡£
	  2.ʹÄÜÒý½Å¶ÔÓ¦µÄʱÖÓ¡£
	  3.ÅäÖÃÒý½ÅÐÅÏ¢*/
	
	//¶¨ÒåÒý½Å½á¹¹Ì壺
	GPIO_InitTypeDef GPIO_InitStruct;
	
	//ʹÄÜʱÖÓ£º
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC,ENABLE);
	
	//ÅäÖÃÒý½ÅÐÅÏ¢(KEY0)£º
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	
	//ÅäÖÃKEY1£º
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //ÉèÖóÉÉÏÀ­ÊäÈë

	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//ÅäÖð´¼üWK_UP:
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
}

void KEY_Scan(void)
{
	static u8 key_up = 1;				//°´¼üËÉ¿ª±ê־λ
	if(key_up && (KEY_0 == 0||  KEY_1  == 0|| KEY_1 == 1))
	{
		//delay_ms(10);						  //È¥¶¶¶¯
		key_up = 0;
		if(KEY_0 == 0)
		{
			GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
			GPIO_SetBits(GPIOA,GPIO_Pin_8);
			//delay_ms(1000);
		}
		else if(KEY_1 == 0)
		{
			GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
			GPIO_SetBits(GPIOD,GPIO_Pin_2);
			//delay_ms(1000);
		}
		else if(KEY_2 == 1)
		{
			GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
			GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
		}
	}
	else if(KEY_0==1&&KEY_1==1&&KEY_2==0)
	{
		key_up = 1;
	}
}

#ifndef __KEY_H
#define __KEY_H

#include "stm32f10x.h"

#define KEY_0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)			//¶ÁÈ¡°´¼üµÄ״̬
#define KEY_1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)
#define KEY_2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)

void KEY_Init(void);
void KEY_Scan(void);						//°´¼üɨÃ躯Êý

#endif

(3)delay代码:

#include "delay.h"

static uint16_t fac_ms = 8;

extern void xPortSysTickHandler(void);

//systickÖжϷþÎñº¯Êý,ʹÓÃucosʱÓõ½
void SysTick_Handler(void)
{	
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//ϵͳÒѾ­ÔËÐÐ
    {
        xPortSysTickHandler();	
    }
}

void delay_us(uint32_t us)
{
	uint32_t i;
	
	//1.Ñ¡ÔñHCLKʱÖÓ£¬²¢ÉèÖõδðʱÖÓ¼ÆÊýÖµ
	SysTick_Config(72);
	
	for(i = 0;i < us;i++)
	{
		while(!((SysTick->CTRL) & (1 << 16)));		//µÈ´ý¼ÆÊýÍê³É
	}
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	//Ñ¡ÔñSTCLKʱÖÓÔ´£¬²¢Ê§Äܶ¨Ê±Æ÷
}

void delay_ms(u32 nms)
{	
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//ϵͳÒѾ­ÔËÐÐ
	{		
		if(nms>=fac_ms)						//ÑÓʱµÄʱ¼ä´óÓÚOSµÄ×îÉÙʱ¼äÖÜÆÚ 
		{ 
   			vTaskDelay(nms/fac_ms);	 		//FreeRTOSÑÓʱ
		}
		nms%=fac_ms;						//OSÒѾ­ÎÞ·¨ÌṩÕâôСµÄÑÓʱÁË,²ÉÓÃÆÕͨ·½Ê½ÑÓʱ    
	}
	delay_us((u32)(nms*1000));				//ÆÕͨ·½Ê½ÑÓʱ
}

void delay_xms(uint32_t ms)								//·â×°ÈÎÎñÇл»µÄÑÓʱº¯Êý
{
	if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)				//Èç¹ûϵͳÒѾ­ÔÚÔËÐУ¬Ôò¿ªÊ¼ÑÓʱ
	{
		if(ms >= fac_ms)
		{
			vTaskDelay(ms / fac_ms);
		}
		ms %= fac_ms;													//µ±OSÎÞ·¨ÌṩÕâôСµÄÑÓʱʱ£¬Ê¹ÓÃÆÕͨÑÓʱ
	}
	delay_ms((uint32_t)(ms*1000));				//ÆÕͨÑÓʱ
}






#ifndef __DELAY_H
#define __DELAY_H

#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"

void delay_us(uint32_t us);									//ÑÓʱ΢Ãë
void delay_ms(uint32_t ms);									//ÑÓʱºÁÃë

void delay_xms(uint32_t ms);								//·â×°ÈÎÎñÇл»µÄÑÓʱº¯Êý

#endif

5.运行结果:

6.总结:

动态创建任务是系统自动分配内存,设置好相关的宏定义后,直接对应函数API即可。删除任务时也是利用API函数去完成。

在做本文实验,一开始每当按下按键时,程序就跑飞了。后面才发现,用来是按键部分的延时有问题。当时移植FreeRTOS后,delay部分的延时函数需要进行修改。本文为了方便实验,取消了按键的防止抖动延时。此处需要注意,当需要使用非FreeRTOS的延时函数时,一定要配置好新的delay延时函数。

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

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

相关文章

Eagle for Mac v1.9.13注册版:强大的图片管理工具

Eagle for Mac是一款专为Mac用户设计的图片管理工具&#xff0c;旨在帮助用户更高效、有序地管理和查找图片资源。 Eagle for Mac v1.9.13注册版下载 Eagle支持多种图片格式&#xff0c;包括JPG、PNG、GIF、SVG、PSD、AI等&#xff0c;无论是矢量图还是位图&#xff0c;都能以清…

软考 系统架构设计师系列知识点之大数据设计理论与实践(11)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之大数据设计理论与实践&#xff08;10&#xff09; 所属章节&#xff1a; 第19章. 大数据架构设计理论与实践 第3节 Lambda架构 19.3.6 Lambda与其它架构模式对比 Lambda架构的诞生离不开很多现有设计思想和架构的铺垫…

ctfhub-ssrf(2)

1.URL Bypass 题目提示:请求的URL中必须包含http://notfound.ctfhub.com&#xff0c;来尝试利用URL的一些特殊地方绕过这个限制吧 打开环境发现URL中必须包含http://notfound.ctfhub.com&#xff0c;先按照之前的经验查看127.0.0.1/flag.php,发现没什么反应&#xff0c;按照题…

excel表格如何筛选重复的内容并单独显示

在处理Excel数据时&#xff0c;遇到大量数据时需要筛选数据中的重复值并单独显示出来&#xff0c;那么此时该如何处理呢&#xff1f;事实上在Excel表格中筛选出重复的内容并单独显示的方法有很多种&#xff0c;以下是其中常用的3种&#xff1a; 方法一&#xff1a;使用条件格式…

每日OJ题_多源BFS①_力扣542. 01 矩阵(多源BFS解决最短路原理)

目录 多源BFS解决最短路算法原理 力扣542. 01 矩阵 解析代码 多源BFS解决最短路算法原理 什么是单源最短路 / 多源最短路&#xff1f; 之前的BFS解决最短路都是解决的单源最短路。 画图来说&#xff0c;单源最短路问题即为&#xff1a; 而对于多源最短路问题: 如何解决此…

全球排名前十的搜索引擎,你猜百度排名在第几位?bing稳居二位!

通常情况下&#xff0c;营销人员在争夺其在线业务的流量时会非常关注Google&#xff0c;无论是通过他们的网站&#xff0c;博客文章还是其他形式的内容。考虑到谷歌无疑是最受欢迎的搜索引擎&#xff0c;拥有超过85%的搜索市场份额&#xff0c;这是有道理的。 但这种受欢迎程度…

STM32使用HAL库解码433遥控芯片EV1527

1、首先了解一下433遥控芯片ev1527的基本资料&#xff1a; 这是他编码的关键信息&#xff1a; 也就是说&#xff0c;一帧数据是&#xff1a;一个同步码20位内码4位按键码。 内码20位2^201048576个地址。 发送就是一帧数据接一帧数据不间断发送。 2、解码思路 从上面的帧结构…

node-mysql数据库的下载与安装

01 mysql数据库的安装 网址&#xff1a;mysql.com/downloads/ 打开之后往下翻 点击 MySQL Community (GPL) Downloads 》 点击 MySRL Community Server 再点击 No thanks,just stant my download. 02 安装mysql 03 安装完成之后检查mysql服务是否开启 services.msc 04 启动…

vue3【详解】 vue3 比 vue2 快的原因

使用 Proxy 实现响应式 vue3使用的 Proxy 在处理属性的读取和写入时&#xff0c;比vue2使用的defineProperty 有更好的性能&#xff08;速度加倍的同时&#xff0c;内存还能减半&#xff01;&#xff09; 更新类型标记 Patch Flag 在编译模板时&#xff08;将vue语法转换为js描…

Seal^_^【送书活动第一期】——《Vue.js+Node.js全栈开发实战(第2版)》

Seal^_^【送书活动第一期】——《Vue.jsNode.js全栈开发实战&#xff08;第2版&#xff09;》 一、参与方式二、本期推荐图书2.1 前 言2.2 作者简介2.3 图书简介2.4 本书特色2.5 编辑推荐2.6 书籍目录 三、正版购买 一、参与方式 1、关注博主的账号。 2、点赞、收藏、评论博主的…

如何判断两个IP地址是否在同一网段?

要判断两个IP地址是否在同一网段&#xff0c;首先需要对IP地址和子网掩码有深入的理解。IP地址是互联网协议地址&#xff0c;用于在IP通信中标识和定位每台设备的逻辑地址。而子网掩码则是一个32位的地址掩码&#xff0c;用于将IP地址划分为网络地址和主机地址两部分。通过比较…

9月BTE第8届广州国际生物技术大会暨展览会,全媒体聚焦下的高精尖行业盛会

政策春风助力&#xff0c;共迎大湾区生物医药行业50亿红利 今年3月“创新药”首次写入国务院政府工作报告之后&#xff0c;广州、珠海、北京多地政府纷纷同步出台了多项细化政策&#xff0c;广州最高支持额度高达50亿元&#xff0c;全链条为生物医药产业提供资金支持&#xff…

【C++】开始了解反向迭代器

送给大家一句话&#xff1a; 重要的东西眼睛是看不到的 — 《小王子》 反向迭代器 1 前言2 反向迭代器3 复刻反向迭代器3.1 加减操作3.2 判断操作3.3 访问操作 4 链表的反向迭代器Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff0…

SQVI创建以及生成程序

SAP数据快速查询工具&#xff1a;Sqvi-QuickView 项目实施&运维阶段&#xff0c;为了快速获取一些透明表数据&#xff0c;一开始接触项目肯定会通过大量的数据表查找&#xff0c;然后线下通过EXCEL通过VLOOKUP进行数据关联&#xff0c;这种方式在关联数据较少的情况比较适应…

【源码】2024新版二开版抢单刷单系统,前端简体、繁体双语言-支持倒计时抢单,后台指定派单连单卡单

CD&#xff1a;获取方式联系小编 微信&#xff1a;uucodes 公众号&#xff1a;资源猿 小编提供资源代找&#xff0c;环境搭建&#xff0c;源码部署调试等业务&#xff0c;需要的可以联系

APP广告变现项目要怎么去做,需要考虑哪些方面!!

要开始一个APP广告变现项目&#xff0c;您可以按照以下步骤进行操作&#xff1a; 制定商业计划&#xff1a;确定您的目标市场、目标受众和变现方式。了解竞争对手和市场趋势&#xff0c;并制定相应的推广策略。 开发APP&#xff1a;找到合适的开发团队或开发者来设计和开发您…

机器学习在安全领域的应用:从大数据中识别潜在安全威胁

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

微纤维眼镜清洁布的革命性进化

在日常生活中&#xff0c;眼镜是许多人不可或缺的日常用品&#xff0c;无论是视力矫正还是防护眼睛免受阳光的伤害。然而&#xff0c;眼镜的清洁常常是一个令人头疼的问题&#xff0c;特别是在面对指纹、灰尘和其他污垢时。传统的清洁方法往往需要化学清洁剂&#xff0c;不仅繁…

Spring Boot 中Mybatis使用Like的使用方式和注意点

说明 模糊查询在项目中还是经常使用的&#xff0c;本文就简单整理Mybatis中使用Like进行模糊查询的几种写法以及一些常见的问题。 使用Springboot简单配置一下Mybatis&#xff0c;然后进行说明。Springboot集成Mybatis这里就不做介绍了&#xff0c;这里我们主要介绍一下在mybat…

【leetcode面试经典150题】59. 合并两个有序链表(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…