嵌入式全栈开发学习笔记---数据结构(顺序表)

news2025/1/21 2:53:47

目录

顺序结构

顺序表初始化

顺序表插入

顺序表遍历操作

顺序表前驱和后继

顺序表查找操作

顺序表删除操作

顺序表清空销毁

顺序表销毁操作

完整代码

List.c

List.h

Main.c

顺序表优缺点(面试可能会考)


上一节我们介绍了数据结构的一般概念,并且介绍了线性结构中两种存储形式:顺序结构(顺序存储)和链式存储(链表)。

那么本节就首先来具体学习顺序结构:

顺序结构

顺序表应该支持以下操作:

初始化操作,建立一个空的顺序表

InitList(*L);  

判断顺序表是否为空        

ListEmpty(L);    

清空顺序表

ClearList(*L);

获取第i个位置的元素,存放在e中

GetElem(L, i, *e);

查找于e相等的元素,返回元素的位置

LocateElem(L, e);  

在第i个位置插入元素e

ListInsert(*L, i, e);     

删除第i个位置的元素,保存在e中

ListDel(*L, i, *e);  

获取顺序表的长度     

ListLength(L);                     

注:我们后面会为每一种操作封装成一个函数。

先说顺序表初始化:

顺序表初始化

顺序表存放数据一定是从第一个位置开始放。

后面存放的数据不允许中间有位置空着,必须是相继存放的形式。数据的值不允许是连续的,比如1后面不一定是2,也可以是3或者其他任何数,但是放的位置必须是相继连续的。

后面的数据也可以是放在第一个位置,然后将第一个位置上的数据挤到后面的位置。

比如以下两种存放方式都是可以的。

如何表示顺序表

struct SequenceList

{

        int data[SIZE]; //顺序表起始地址和容量

        int length; //顺序表长度

};

typedef struct SequenceList seqList;

注意:容量和长度是不一样的,比如现在这个顺序表:

它的容量是6,目前长度是1。

现在我们开始在Linux终端写代码演示一下:

先创建一个目录datastruct;

然后再在datastruct目录下创建一个sequencelist的目录;

再在sequencelist目录下创建文件,我们在数据结构这部分写代码的时候一般分为三个文件,一个是头文件(.h),两个源文件(.c)

三个文件的作用:

我们先来看看头文件应该怎么写:

我们写头文件的第一步最好先写好这个框架

#ifndef _LIST_H #define _LIST_H #endif这三行代码的作用是防止头文件被重复定义。

#ifndef _LIST_H #define _LIST_H #endif这三行代码为什么能防止重复定义呢?

首先重复定义就是比如你某天在主文件中写代码的时候重复定义了#include <stdio.h>

那编译的时候会不会报错呢?

编译不会报错。为什么呢?

因为我们所包含的stdio.h这头文件中就有这三行代码

我们复习Linux C语言的时候讲过编译的过程,在预处理环节,头文件会被展开,展开后就会遇到这句话#ifndef _STDIO_H,这时编译器就会看一下,如果没有定义这个STDIO.H,那么就执行 # define _STDIO_H,把这个宏定义一下,这时STDIO.H就是被定义过了。

等到第二次你又去包含这个头文件的时候,预处理的时候有会展开这个头文件,又遇到#ifndef _STDIO_H,这时编译器会看一下,知道STDIO.H就是被定义过了,不满足条件了,则编译器会跳过# define _STDIO_H及其后面的代码,直接到#endif。

包含头文件的写法有两种:一种是用尖括号包含的头文件,一种是双引号包含的头文件。

这两种有什么区别呢?

尖括号包含的头文件默认去系统指定的目录下找头文件;

双引号包含的头文件默认在当前目录下找头文件,如果找不到的话也会去系统指定的目录下去找这个头文件。

我们继续完成我们本节的头文件list.h,声明结构体及其他。

图片更正:#define SUCCESS 1000

然后我们在主文件main.c中创建一个顺序表,我们是用结构体来表示顺序表列表的,创建顺序表即定义一个结构体变量。

list.c用来实现函数。

同时编译main.c 和list.c

这样顺序表初始化就成功了

顺序表插入

比如说我们现在有这样一个顺序表,还没有存满数据,还能够插入数据

以上这个顺序表我们可以从第一个位置插入,在第二个位置和第三个位置插入也行,这样就会把原本这个位置上的数据挤到后面的位置。我们也可以在第四个位置插入,我们将这个中插入方式叫做尾插法。但是,我们不能直接在第五个位置及其后面的位置插入,这样的话就会空出第四个位置,这样就不是所谓的顺序表了。

插入的方法就是比如说想要插入到第二个位置,那么就将第二个位置上的数及其后面的数都往后挪一个位置,然后将要插入的数插入到空出来的第二个位置。挪位置时的循环操作次数是顺序表长度-要插入的位置+1。

代码演示:

List.c

List.h

在头文件中声明一下这个函数

Main.c

运行结果:

如果插入11那最后一个就会报错,因为我们设置的顺序表容量总共是SIZE =10

顺序表遍历操作

虽然我们看到插入成功了,但是数据到底有没有插入到顺序表里面,我们是看不到的,接下来我们就来遍历一下这个顺序表。

代码演示:

List.c

List.h

在头文件中声明一下这个函数

Main.c

运行结果:

顺序表前驱和后继

我们接下来演示一下如何获得一个顺序表的前驱和后继

代码演示:

List.c

在List.h里面声明一下这两个函数

main.c

运行结果:

顺序表查找操作

查找有两种情况:一种是给定位置,返回该位置的元素是几;另一种是定位,给定一个元素,查找这个元素的位置。

代码演示:

List.c

在List.h里面声明一下这两个函数

Main.c

运行结果:

顺序表删除操作

比如这样一个顺序表,我们想要将第二个位置上的数据删除掉,那么这个位置将会变成空的,根据顺序表的特点,我们必须要将这个位置后面的数据向前挪,补上这个空缺。挪动的次数是长度-被删除的位置。

删除操作最重要的是判断删除的位置是否合法。比如说想要删除第四个位置肯定是不行的,因为这个顺序表中的第四个位置是空的。因此我们要判断一下位置是否合法。

代码演示:

List.c

在List.h中声明一下这个函数

Main.c

运行结果:

求顺序表的长度和判断顺序表是否为空这个比较简单就不写代码了。求顺序表的长度,我们只要写一个return l->length;因为我们length本身就是结构体里面的成员, return l->length如果为零,说明顺序表位空。

顺序表清空销毁

顺序表清空,我们只要将顺序表的长度变成零即可。到时候我们要插入数据的话就必然是从顺序表的第一个位置开始插入。

代码演示:

List.c

在List.h里面声明这个函数

Main.c

运行结果:

顺序表清空成功了,如何来验证呢?我们遍历一下就可以了,在主函数中调用遍历函数。

代码演示:

运行结果:

没有遍历出元素,说明的确是清空了。

顺序表销毁操作

接下来是销毁操作

我们将malloc申请的data指向的那块空间即顺序表给释放掉就是销毁操作。这时data会变成野指针,我们要将data置为空指针。

代码演示:

List.c

在list.h里面声明一下这个函数

Main.c

运行结果:

销毁成功后按理是不能再插入数据了,我们调用插入数据的函数验证一下

代码演示:

运行结果:

插入失败,说明data指向的那块内存的确被销毁了。

完整代码

List.c

//实现所有的函数
#include "list.h"
#include <stdlib.h>//malloc的头文件
#include <stdio.h>//printf的头文件

//顺序表的初始化操作,定义函数
int init_list(List *l)//把结构体的地址传过来
{
	if(NULL==l)//入参判断,防止传过来空指针
	{
		return FAILURE;
	}

	l->data=(int*)malloc(sizeof(int)*SIZE);
	if(NULL==l->data)
	{
		return FAILURE;
	}

	l->length=0;

	return SUCCESS;
}

//顺序表的插入操作
int insert_list(List *l,int p,int num)
{
	//判断是否空指针
	if(NULL==l||NULL==l->data)
	{
		return FAILURE;
	}
	//判断顺序表是否满
	if(l->length>=SIZE)
	{
		return FAILURE;
	}
	//判断位置是否合法
	if(p>l->length+1)
	{
		return FAILURE;
	}
	//挪位置
	int i;
	for(i=0;i<l->length-p+1;i++)
	{
		l->data[l->length-i]=l->data[l->length-1-i];
	}
	//插入
	l->data[p-1]=num;//p是位置,p-1是下标
	l->length++;//插入数据后,长度加1
	return SUCCESS;
}

//顺序表的遍历操作
void traverse_list(List l)
{
	int i;
	for(i=0;i<l.length;i++)
	{
		printf("%d ",l.data[i]);
	}
	printf("\n");
}

//顺序表获取前驱操作
int get_prior_list(List l,int num,int *r)
{
	int i;
	//将num和顺序表中的数进行匹配,看看顺序表中有没有这个数
	for(i=1;i<l.length;i++)//第一个位置上的数没有前驱,所以i从1开始
	{
		if(l.data[i]==num)
		{
			*r=l.data[i-1];
			return SUCCESS;
		}
	}
	return FAILURE;
}

//顺序表获取后继操作
int get_next_list(List l,int num, int*r)
{
	int i;
	for(i=0;i<l.length-1;i++)//最后一个位置上的数没有后继,所以循环次数l.length-1
	{
		if(l.data[i]==num)
		{
			*r=l.data[i+1];
			return SUCCESS;
		}
	}
	return FAILURE;
}

//顺序表的查找操作
int find_list(List l,int p, int *n)
{
	//先判断位置是否合法
	if(p<=0||p>l.length)
	{
		return FAILURE;
	}
	*n=l.data[p-1];//p-1是下标
	return SUCCESS;
}

//顺序表的定位操作
int locate_list(List l, int num, int *p)
{
	int i;
	for(i=0;i<l.length;i++)
	{
		if(num==l.data[i])
		{
			*p=i+1;//记录位置
			return SUCCESS;
		}
	}
	return FAILURE;
}

//顺序表的删除操作
int delete_list(List *l,int p,int *n)
{
	//入参判断
	if(NULL==l||NULL==n)//两个指针不能为空
	{
		return FAILURE;
	}
	//判断删除的位置是否合法
	if(p>l->length||p<=0)//删除的位置超出了范围或者是个空表则不能删除
	{
		return FAILURE;
	}

	*n=l->data[p-1];//要删除的那个元素

	//挪位置,即用后一个元素覆盖要删除的元素,后面的也依次覆盖
	int i;
	for(i=0;i<l->length-p;i++)
	{
		l->data[p-1+i]=l->data[p+i];
	}
	//这种覆盖的方式,最后一个元素并没有东西覆盖它,但是留着也没有影响,我们只要长度减1就行,下次要插入元素的话自然就能将它覆盖了
	l->length--;
	return SUCCESS;
}

//顺序表的清空操作
int clear_list(List *l)
{
	//入参判断
	if(NULL==l)
	{
		return FAILURE;
	}

	l->length=0;//清空:直接让长度变成0

	return SUCCESS;

}

//顺序表的销毁操作
int destroy_list(List *l)
{
	//入参判断
	if(NULL==l)
	{
		return FAILURE;
	}

	free(l->data);
	l->data=NULL;
	return SUCCESS;
}

List.h

#ifndef _LIST_H
#define _LIST_H

#define SIZE  10  //宏定义顺序表的容量为10
#define SUCCESS 1000
#define FAILURE 1001

//结构体声明
typedef struct Sequencelist
{
	int *data;//顺序表的起始地址
	int length;//顺序表长度

}List;//将struct Sequencelist{};重命名为List

//声明函数
int init_list(List *l);
int insert_list(List *l,int p,int num);
void traverse_list(List l);
int get_prior_list(List l,int num,int *r);
int get_next_list(List l,int num, int*r);
int find_list(List l,int p, int *n);
int locate_list(List l, int num, int *p);
int delete_list(List *l,int p,int *n);
int clear_list(List *l);



#endif

Main.c

#include <stdio.h>//尖括号包含的头文件默认去系统指定的目录下找头文件
#include "list.h"//双引号包含的头文件默认在当前目录下找头文件
#include <time.h>//time的头文件
#include <stdlib.h>//rand和srand的头文件

int main()
{
	//创建顺序表(定义一个结构体变量)
	List seqList;

	//初始化顺序表,调用函数
	int ret=init_list(&seqList);//如果要修改实参的值,必须要取地址
	if(SUCCESS==ret)
	{
		printf("顺序表初始化成功\n");
	}
	else
	{
		printf("顺序表初始化失败\n");
	}

	//顺序表的插入
	int i,num;
	srand(time(NULL));//设置种子,给srand()函数传的数每次不一样的话,则每次运行的结果就会不一样,因此我们用time()作为参数
	for(i=0;i<11;i++)//插入i个数
	{

	 	num=rand()%20;//产生随机数,如果种子一样,则产生的数字是一样,否则每次产生的数不一样
		//任何数%20都得到一个0~19范围内的数
		ret=insert_list(&seqList,i+1,num);//i是顺序表中data的元素的下标,i+1是位置,num是要插入的数
		if(SUCCESS==ret)
		{
			printf("插入%d成功\n",num);//插入随机数成功
		}
		else
		{
			printf("插入%d失败\n",num);
		}
	}

	//遍历顺序表,类似遍历数组
	traverse_list(seqList);

	//获得顺序表前驱
	num=rand()%20;//获得一个随机数的前驱
	int result;//保存结果
	ret=get_prior_list(seqList,num,&result);//因为要找到前驱并赋值给result,所以要取地址
	if(SUCCESS==ret)
	{
		printf("%d的前驱是%d\n",num,result);
	}
	else
	{
		printf("%d不存在前驱\n",num);
	}

	//获取后继元素
	ret=get_next_list(seqList, num, &result);
	if(SUCCESS==ret)
	{
		printf("%d的后继是%d\n",num,result);
	}
	else
	{
		printf("%d不存在后继\n",num);
	}

	//查找操作
	int p=rand()%15;//随机产成一个位置,这个位置在0~14范围内,比顺序表的容量大,有可能查找是失败的
	ret=find_list(seqList,p,&num);//num用来保存查找的那个元素
	if(SUCCESS==ret)
	{
		printf("第%d个元素是%d\n",p,num);
	}
	else
	{
		printf("第%d不存在\n",p);
	}
	//定位操作
	num=rand()%20;//随机给定一个元素,查找它的位置是几
	ret=locate_list(seqList, num, &p);
	if(SUCCESS==ret)
	{
		printf("元素%d的位置是%d\n",num,p);
	}
	else
	{
		printf("元素%d不存在\n",num);
	}

	//删除元素
	for(i=0;i<5;i++)//删除5个元素
	{
		p=rand()%10;//随机删除一个位置
		ret=delete_list(&seqList,p,&num);//因为长度要改变,所以seqList要取地址,被删除掉的元素保存在num里面
		if(SUCCESS==ret)
		{
			printf("删除第%d个元素%d成功\n",p,num);
		}
		else
		{
			printf("删除第%d个元素失败\n",p);
		}
	}

	//清空操作
	ret=clear_list(&seqList);
	if(SUCCESS==ret)
	{
		printf("顺序表清空成功\n");		
	}
	else
	{
		printf("顺序表清空失败\n");
	}

	//遍历顺序表,类似遍历数组
	traverse_list(seqList);

	//销毁操作
	ret=destroy_list(&seqList);//因为我们要将结构体中的data变为空指针,所以要取地址
	if(SUCCESS==ret)
	{
		printf("顺序表销毁成功\n");		
	}
	else
	{
		printf("顺序表销毁失败\n");
	}

	//顺序表的插入
	srand(time(NULL));//设置种子,给srand()函数传的数每次不一样的话,则每次运行的结果就会不一样,因此我们用time()作为参数
	for(i=0;i<11;i++)//插入i个数
	{

	 	num=rand()%20;//产生随机数,如果种子一样,则产生的数字是一样,否则每次产生的数不一样
		//任何数%20都得到一个0~19范围内的数
		ret=insert_list(&seqList,i+1,num);//i是顺序表中data的元素的下标,i+1是位置,num是要插入的数
		if(SUCCESS==ret)
		{
			printf("插入%d成功\n",num);//插入随机数成功
		}
		else
		{
			printf("插入%d失败\n",num);
		}
	}
	return 0;
}

顺序表优缺点(面试可能会考)

我们在实际的开发过程中涉及到的数据量是比较大的,数组可能无法解决问题,因为我们可以借助顺序表来解决问题。

而且顺序表相比较于链表有一个好处就是访问数据比较简单,我们直接在写元素的下标就行,比如我们要访问第9个元素,我们只需要:l->data[8]这样就能访问。

但是顺序表在头部插入的效率低,因为插入一个数据,之后的数据都得往后挪;而且容量有限,一开始我们用malloc申请了一块空间后,不够用了的话需要调用realloc()来扩展内存。

实际上,在开发的过程中我们也很少使用顺序表,我们用的比较多的是链表,因为链表不需要申请一块连续的内存。

下回我们就来具体学习链表了,敬请关注!

QQ交流群:963138186

本篇就到这里,下篇继续!欢迎点击下方订阅本专栏↓↓↓

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

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

相关文章

【ModelSim】仿真问题记录

1、波形出不全&#xff1a; 1、甚至连clk波形都出不来 2、个别波形只有到仿真结束的时候才出现 解决办法&#xff1a; 1、添加波形需要是实例中的net 2、排查是否存在声明与示例的位宽不一致的信号 3、观察是否存在未初始化的变量寄存器 4、缩短整个仿真的步长 2、Instance列…

【HBZ分享】spring启动时自动装配的位置

自动装配流程 springboot启动时&#xff0c;自动装配逻辑在SpringBootApplication这个符合注解中的EnableAutoConfiguration新版springboot3会扫描META-INF的spring文件夹下的org.springframework.boot,autoconfigure,AutoConfiguration.imports文件&#xff0c;会把这里所有写…

FSMC--灵活的静态存储控制器

&#xff08;1&#xff09;在STM32F1系列&#xff08;及F407&#xff09;的芯片上封装了FSMC外设&#xff0c;支持拓展SARM作为RAM。 &#xff08;2&#xff09;SRAM和SDRAM的区别&#xff1a; 存储结构&#xff1a;SRAM使用锁存器、SDRAM使用电容通讯方式&#xff1a;SRAM多…

Leaf分布式ID

文章目录 系统对Id号的要求UUIDsnowflakeLeafLeaf-snowflakeLeaf-segmentMySQL自增主键segment双buffer 系统对Id号的要求 1、业务 1&#xff09;全局唯一性&#xff1a;不能出现重复的ID号&#xff0c;既然是唯一标识&#xff0c;这是最基本的要求 2&#xff09;趋势递增&a…

使用LLM(Large Language Model)进行主题建模

随着互联网技术的快速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域取得了显著的进步。其中&#xff0c;大型语言模型&#xff08;LLM&#xff09;在文本生成任务中表现尤为抢眼。本文旨在探讨LLM在主题建模方面的优势&#xff0c;以及如何将其应用于文本生成任…

深度图进行运算检测物体表面粗糙度

文章目录 应用场景算法原理核心代码应用场景 不同程度凹凸的零件表面粗糙度对零件的磨损产生影响,很大程度上关系到产品性能和使用寿命。不同于单独使用的产品,零件需要在装配中与其他零件相连,密封性和磨损量是厂商需要考虑的一大加工要素;其次,产品外观和触感也会影响到…

数据结构链表2(常考习题1)(C语言)

移除链表元素&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 解题思路&#xff1a; 情况1&#xff1a; 情…

【vluhub】skywalking

SkyWalking是一个开源监控平台&#xff0c;用于从服务和云原生基础设施收集、分析、聚合和可视化数据 低版本存在sql注入漏洞 访问地址 http://192.168.203.12:8080/graphql burpsuite抓数据包 替换 {"query":"query queryLogs($condition: LogQueryConditi…

安装STM32开发工具:STM32CubeMX、STM32CubeIDE、STM32CubeCLT

ST官网地址&#xff1a;https://www.st.com/content/st_com/en.html ST官网因为链接原因下载会比较慢&#xff0c;推荐使用STMCU中文官网&#xff0c;下载很通畅&#xff1a;STMCU中文官网 安装Java 在安装STM32开发软件STM32CubeMX和STM32CubeIDE、STM32CubeCTL之前&#x…

浏览器事件循环详解

1. 浏览器的进程模型 1.1. 何为进程&#xff1f; 程序运行需要有它自己的专属内存空间&#xff0c;可以把这块内存空间简单的理解为进程。 每个应用至少有一个进程&#xff0c;进程之间相互独立&#xff0c;即使要通信&#xff0c;也需要双方同意。 1.2. 何为线程&#xff1f…

【Linux】进程间通信(3):共享内存

目录 一、共享内存概述 二、共享内存相关函数 1、shmget函数 2、ftok函数 3、shmctl函数 4、 shmat函数 5、 shdt函数 三、使用共享内存相关函数管理共享内存的一般过程 1. 生成唯一的键值 2. 创建或获取共享内存段 3. 连接到共享内存段 4. 操作共享内存 5. 断开…

2024 NVIDIA开发者社区夏令营环境配置指南(Win Mac)

2024 NVIDIA开发者社区夏令营环境配置指南(Win & Mac) 1 创建Python环境 首先需要安装Miniconda&#xff1a; 大家可以根据自己的网络情况从下面的地址下载&#xff1a; miniconda官网地址&#xff1a;https://docs.conda.io/en/latest/miniconda.html 清华大学镜像地…

对提高数据和指令缓存命中率方法的验证

对于如何写出让CPU跑得更快的代码这一问题&#xff0c;我看到了两种方法&#xff0c;分别是&#xff1a;1、提高数据缓存命中率&#xff1b;2、提高指令缓存命中率。 本文对这两种方法进行了简单的验证&#xff0c;并提供了示例代码。 本文基于2.3 如何写出让 CPU 跑得更快的代…

大规模深度学习推理引擎是什么?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 首先&#xff0c;我们来理解 “深度学习”&#xff1a;它是人工智能的一个重要分支&#xff0c;模仿人脑的神经网络结构&#xff0c;运用多层神经网络来学习和解析数据。这些神经网络能够从庞大的数据集…

二、版本更新与插件安装

版本更新 点击版本管理 点击刷新列表后点击一键更新&#xff0c;即可完成更新&#xff08;注意完成更新必须要关闭正在运行的服务&#xff09; 更新拓展&#xff08;更新插件&#xff09; 点击拓展-刷新列表-一键更新 即可 注意&#xff1a;操作完成以后必须重新启动方可生效…

(六)activiti-modeler 设计器属性编辑弹窗bug修复

BUG重现 在使用流程设计器时&#xff0c;经常碰到弹窗不小心关闭&#xff0c;比如不小心点击了灰色背景上&#xff0c;此时BUG就出现了。弹窗被关闭了&#xff0c;分配用户属性被置空了&#xff0c;以前有数据也被清空了&#xff0c;还无法再次点击弹窗编辑。 不仅仅是分配用…

deque和优先级队列

咱学完栈和队列之后&#xff0c;又了解到了vector和list&#xff0c;更深入的了解到了它们各自的优势&#xff0c;那么有没有可能结合它们的优点摒弃弱点呢&#xff0c;其实是有人这么试过的&#xff0c;不过咱还在学vector和list就证明他可能没成功&#xff0c;不过并不影响我…

python中类class的魔法方法

开始介绍之前&#xff0c;我们先看下之前文章我们介绍过的内置类merryview的一些方法&#xff0c;如下图所示&#xff1a; 有很多双下划线开始和结束的method&#xff0c;这么多method是做啥子用的呢&#xff1f; 其实这些方法就是我们常说的魔法方法&#xff0c;也是python中的…

【代码随想录】二分查找

文章为代码随想录的学习笔记&#xff0c;链接&#xff1a; 代码随想录 只要看到面试题中给出的数组是有序数组&#xff0c;都可以想一想是否可以使用二分法。 基本概念 二分查找要求线性表必须采用顺序存储结构&#xff0c;而且表中元素按关键字有序排列。‘ 查找过程&…

2024年华数杯数学建模竞赛——赛题浅析

本次华数杯与国赛同频【第一天下午六点发题&#xff0c;第四天下午八点收卷】&#xff0c;一共74小时。难度约为国赛的0.8&#xff0c;题量约为国赛的0.8-0.9.非常适合作为国赛前的练手赛。下面为大家带来本次华数杯的选题建议&#xff0c;希望对大家有所帮助。 一图流 选题人…