深入解析顺序表:揭开数据结构的奥秘,掌握顺序表的精髓
- 💓 博客主页:江池俊的博客
- ⏩ 收录专栏:数据结构探索
- 👉专栏推荐:✅C语言初阶之路 ✅C语言进阶之路
- 💻代码仓库:江池俊的代码仓库
- 🔥编译环境:Visual Studio 2022
- 🎉欢迎大家点赞👍评论📝收藏⭐
文章目录
- 🚀线性表
- 🚀顺序表
- 🚨概念及结构
- 🎈. 静态顺序表:使用定长数组存储元素。
- 🎈. 动态顺序表:使用动态开辟的数组存储。
- 🚀接口实现
- 📌有哪些接口呢
- 📌准备工作
- 📌初始化
- 📌扩容
- 📌顺序表打印
- 📌顺序表销毁
- 📌尾插
- 📌尾删
- 📌头插
- 📌头删
- 📌指定pos下标位置插入数据
- 📌删除pos位置的数据
- 📌查找
- 📌修改pos位置的数据
- 🚀源码
- 🌴SeqList.h 文件
- 🌴SeqList.c 文件
- 🌴Test.c 文件
🚀线性表
【维基百科】 线性表(英语:Linear List)是由n(n≥0)个数据元素(结点)a[0],a[1],a[2]…,a[n-1]组成的有限序列。
其中:
- 数据元素的个数n定义为表的长度 = “list”.length() (“list”.length() = 0(表里没有一个元素)时称为空表)
- 将非空的线性表(n>=1)记作:(a[0],a[1],a[2],…,a[n-1])
- 数据元素a[i](0≤i≤n-1)只是个抽象符号,其具体含义在不同情况下可以不同
一个数据元素可以由若干个数据项组成。数据元素称为记录,含有大量记录的线性表又称为文件。这种结构具有下列特点:存在一个唯一的没有前驱的(头)数据元素;存在一个唯一的没有后继的(尾)数据元素;此外,每一个数据元素均有一个直接前驱和一个直接后继数据元素。
线性表(linear list)是n
个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构
,也就说是连续的一条直线。但是在物理结构
上并不一定是连续的,线性表在物理上存储时,通常以数组
和链式结构
的形式存储。
🚀顺序表
🚨概念及结构
【维基百科】 顺序表是在
计算机内存中
以数组
的形式保存的线性表
,是指用一组地址
连续的存储单元
依次存储数据元素的线性结构,使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
即:顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改
。
🎈. 静态顺序表:使用定长数组存储元素。
🎈. 动态顺序表:使用动态开辟的数组存储。
🚀接口实现
静态顺序表
只适用于确定知道需要存多少数据的场景。静态顺序表
的定长数组导致N
定大了,空间开多了浪费,开少了不够用。
所以现实中基本都是使用动态顺序表
,根据需要动态的分配空间大小,所以下面我们实现动态顺序表
。
这里的接口其实就是 接口函数
,这些 接口函数
提供了顺序表的各种基本操作,允许我们对顺序表进行 增、删、查、改
等操作。
📌有哪些接口呢
// 基本 增删查改 接口 --- 命名风格是跟着STL走的,方便后续学习STL
// 顺序表初始化
void SeqListInit(SL* psl);
// 检查空间,如果满了,进行增容 --> 扩容
void SLCheckCapacity(SL* psl);
// 顺序表尾插
void SeqListPushBack(SL* psl, SLDataType x);
// 顺序表头插
void SeqListPushFront(SL* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SL* psl);
// 顺序表头删
void SeqListPopFront(SL* psl);
// 顺序表查找
int SeqListFind(SL* psl, SLDataType x);
//顺序表的修改
void SeqListModify(SL* psl,int pos, SLDataType x);
// 顺序表在pos位置插入x(可以实现头插和尾插)
void SeqListInsert(SL* psl, int pos, SLDataType x);
// 顺序表删除pos位置的值(可以实现头删和尾删)
void SeqListErase(SL* psl, int pos);
// 顺序表打印
void SeqListPrint(SL* psl);
// 顺序表销毁
void SeqListDestroy(SL* psl);
接下来我将带着大家一 一实现这些接口。
📌准备工作
在写顺序表前,我们需要创建工程,这里为了让大家养成模块化的好习惯,我们尽量将代码分成三个文件来写。这里我打开的编译器是 vs 2022,在资源管理器的 头文件
中创建 SeqList.h 文件,此文件作用主要是为了存储各种头文件和接口函数的声明以及顺序表结构体的创建;在源文件中创建 SeqList.c 文件用来实现接口函数,Test.c 文件用来测试顺序表的各个接口。具体如下图所示:
注意:
- 为了能够在顺序表中方便地存储各种类型的数据,我们可以使用
typedef
将要存储的数据类型重命名为SLDataType
,这样在定义顺序表的数据类型时只需要使用SLDataType
就行了,修改数据类型时只需要修改typedef
后面跟着的这个数据类型,这样就大大方便了对不同类型数据的存储。 - 类似的,为了方便结构体的定义和使用,我们也可以使用
typedef
将结构体定义一个简单的别名为SL
。
#pragma once#include<stdio.h>
#include<stdlib.h> // NULL、size_t
#include<assert.h>// 静态的顺序表:使用定长数组存储元素。
// 特点:如果满了就不让插入
// 缺点:N给小了不够用,给多了浪费,这个很难确定
//#define N 100
//typedef int SLDataType; // 给int取别名
//struct SeqList // 创建顺序表
//{
// SLDataType a[N]; // 定长数组
// int size; // 存储的有效数据的个数
//};// 动态顺序表:使用动态开辟的数组存储。
//typedef double SLDatatype;
typedef int SLDataType; //重定义类型名称,方便顺序表对不同类型的数据的存储和操作
typedef struct SeqList // 创建顺序表
{SLDataType* a; //指向动态开辟的数组int size; // 存储的有效数据的个数int capacity; // 容量空间大小
}SL; //将结构体类型取别名为 SL
📌初始化
这里我们实现动态顺序表,所以刚开始时我们可以假设给定顺序表的大小为 4(即能存放4个元素),不够就扩容,顺序表中刚开始是没有元素的。
//顺序表初始化
void SeqListInit(SL* psl)
{//防止psl为空指针(即防止传错结构体地址)assert(psl);psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//判断能否成功开辟空间if (psl->a == NULL){perror("malloc fail");//将系统错误信息输出到屏幕return;}psl->capacity = 4;psl->size = 0;
}
📌扩容
在后续对顺序表进行操作过程中我们会插入数据,如果顺序表空间不够,我们就需要使用
realloc
函数进行扩容。
这里newcapacity
表示扩容后能存放的元素个数(即空间的容量),tmp
表示的是扩容后的空间的地址,如果顺序表的空间为空,就给定能存放4
个元素的空间;如果空间不够,就在原来空间的基础上,增加1
倍的空间(这样也依然无法避免空间的部分浪费,所以就有了链表,后续文章我会为大家带来)。
// 扩容 ---> 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl)
{if (psl->size == psl->capacity){//如果没有空间或者空间不足,就扩容int newcapacity = (psl->capacity == 0 ? 4 : psl->capacity * 2);SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newcapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1); //退出程序}psl->a = tmp;psl->capacity = newcapacity;}
}
📌顺序表打印
打印比较简单,这里我们只需要依次遍历每一个节点就行。
//打印
void SeqListPrint(SL* psl)
{//防止psl为空指针(即防止传错结构体地址)assert(psl);//遍历for (int i = 0; i < psl->size; i++){printf("%d ", psl->a[i]);}printf("\n");
}
📌顺序表销毁
因为是动态开辟的,所以如果空间不用我们就需要销毁掉。如果不销毁会存在内存泄漏的风险,所以这里我们使用
free
函数释放开辟的动态空间,并把有效数据个数和容量空间都置为0
。
//销毁
void SeqListDestroy(SL* psl)
{assert(psl);free(psl->a);psl->a = NULL;psl->size = 0;psl->capacity = 0;
}
📌尾插
尾插就是在最后一个元素的后面插入一个元素(即在
size
下标位置处插入数据),但要注意的是当capacity
空间满了就需要扩容,因此我们要调用SLCheckCapacity
函数。
//尾插
void SeqListPushBack(SL* psl, SLDataType x)
{assert(psl);//psl->a[psl->size] = x;//psl->size++;SLCheckCapacity(psl); // 检查扩容psl->a[psl->size++] = x;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, psl->size, x);
}
📌尾删
尾删其实就是将顺序表最后一个数据删去,要实现这一操作其实只需要将有效数据个数减一就可以了(即
size--
),但是在尾删之前要先判断顺序表中是否有元素,如果没有元素就没有必要删了。
//尾删
void SeqListPopBack(SL* psl)
{assert(psl);//温柔的处理方式//if (psl->size > 0)//{// psl->size--;//}//else//{// printf("没有数据能够再删了!\n");// exit(-1); //退出程序//}//暴力的处理方式assert(psl->size > 0);//确保顺序表中有数据psl->size--;//复用pos下标位置删除数据的函数//SeqListErase(psl, psl->size - 1);
}
📌头插
头插操作其实就是在顺序表下表为
0
的位置插入数据,然后size++
,但是在此之前要判断顺序表容量空间是否已满,所以要先调用SLCheakCapacity
函数。
//头插
void SeqListPushFront(SL* psl, SLDataType x)
{assert(psl);SLCheckCapacity(psl);//挪动数据int end = psl->size -1;while (end >= 0){psl->a[end + 1] = psl->a[end];end--;}psl->a[0] = x;psl->size++;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, 0, x);
}
📌头删
头删的实现其实只需要将顺序表开头后面的数据依次往前挪动,然后将
size--
就可以了,这里要从前往后挪,如果从后往前挪数据会被覆盖。注意:这里与尾删类似,在头删之前要先判断顺序表中是否有元素,如果没有元素就没有必要删了。
//头删
void SeqListPopFront(SL* psl)
{assert(psl);assert(psl->size > 0);//有数据才能删,没数据就会报错int begin = 1;while (begin < psl -> size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;//复用pos效标位置删除数据的函数//SeqListErase(psl, 0);
}
📌指定pos下标位置插入数据
我们只需要将顺序表中pos位置到最后的数据依次往后挪动(从后往前挪),然后将pos下标位置的数据改为要插入的数据,最后
size++
即可。但是我们依然要判断是否满容,所以在插入数据前要调用SLCheakCapacity
函数。同时我们也要判断pos位置是否合理,防止越界访问。
//指定pos下标位置插入数据
void SeqListInsert(SL* psl, int pos, SLDataType x)
{assert(psl);//if (pos > psl->size || pos < 0)//{// printf("pos的下标位置越界");// return;//}//暴力的方式处理(pos下标不能越界)assert(pos >= 0 && pos <= psl->size);//如果没有空间或者空间不足,就扩容SLCheckCapacity(psl);//挪动数据int end = psl->size - 1;while (end >= pos){psl->a[end + 1] = psl->a[end];end--;}psl->a[pos] = x;psl->size++;
}
📌删除pos位置的数据
与头删类似,我们只需要将pos位置后的数据依次往前挪动将pos位置处的数据覆盖,然后再
size--
就可以了。但是要判断pos位置是否合理,防止越界访问。
//删除pos位置的数据(结合SeqListFind函数可以删除指定的数据)
void SeqListErase(SL* psl, int pos)
{assert(psl);assert(pos >= 0 && pos < psl->size);//pos位置需要有数据//挪动数据int begin = pos + 1;while (begin < psl->size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;
}
📌查找
这个比较简单,我们只需要遍历一遍顺序表,查找相应数据,若找到,就返回下标,若没找到,就返回-1。
//查找,找到了返回下标,没找到返回-1
int SeqListFind(SL* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; i++){if (psl->a[i] == x){return i;}}return -1;
}
📌修改pos位置的数据
通过pos下标直接修改
//修改pos位置的数据
void SeqListModify(SL* psl, int pos, SLDataType x)
{assert(psl);assert(pos >= 0 && pos < psl->size);psl->a[pos] = x;
}
🚀源码
🌴SeqList.h 文件
#pragma once#include<stdio.h>
#include<stdlib.h>//NULL、size_t
#include<assert.h>// 静态的顺序表:使用定长数组存储元素。
// 特点:如果满了就不让插入
// 缺点:N给小了不够用,给多了浪费,这个很难确定
//#define N 10000
//typedef int SLDatatype; // 给int取别名
//struct SeqList // 创建顺序表
//{
// SLDatatype a[N]; // 定长数组
// int size; // 存储的有效数据的个数
//};
//静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪
//费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实
//现动态顺序表。// 动态顺序表:使用动态开辟的数组存储。
//typedef double SLDatatype;
typedef int SLDataType; //重定义类型名称,方便顺序表对不同类型的数据的存储和操作
typedef struct SeqList
{SLDataType* a; //指向动态开辟的数组int size; // 存储的有效数据的个数int capacity; // 容量空间大小
}SL;// 基本 增删查改 接口 --- 命名风格是跟着STL走的,方便后续学习STL
// 顺序表初始化
void SeqListInit(SL* psl);// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl);// 顺序表尾插
void SeqListPushBack(SL* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SL* psl);
// 顺序表头插
void SeqListPushFront(SL* psl, SLDataType x);
// 顺序表头删
void SeqListPopFront(SL* psl);
// 顺序表查找
int SeqListFind(SL* psl, SLDataType x);
// 顺序表在pos位置插入x(可以实现头插和尾插)
void SeqListInsert(SL* psl, int pos, SLDataType x);
// 顺序表删除pos位置的值(可以实现头删和尾删)
void SeqListErase(SL* psl, int pos);// 顺序表打印
void SeqListPrint(SL* psl);
// 顺序表销毁
void SeqListDestroy(SL* psl);//顺序表的修改
void SeqListModify(SL* psl, int pos, SLDataType x);
🌴SeqList.c 文件
#include"SeqList.h"//void SeqListInit(SL* psl)
//{
// psl->a = NULL;
// psl->size = 0;
// psl->capacity = 0;
//}//顺序表初始化
void SeqListInit(SL* psl)
{//防止psl为空指针(即防止传错结构体地址)assert(psl);psl->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);//判断能否成功开辟空间if (psl->a == NULL){perror("malloc fail");//将系统错误信息输出到屏幕return;}psl->capacity = 4;psl->size = 0;
}
//销毁
void SeqListDestroy(SL* psl)
{assert(psl);free(psl->a);psl->a = NULL;psl->size = 0;psl->capacity = 0;
}
//打印
void SeqListPrint(SL* psl)
{assert(psl);for (int i = 0; i < psl->size; i++){printf("%d ", psl->a[i]);}printf("\n");
}
// 检查空间,如果满了,进行增容
void SLCheckCapacity(SL* psl)
{assert(psl);if (psl->size == psl->capacity){//如果没有空间或者空间不足,就扩容int newcapacity = (psl->capacity == 0 ? 4 : psl->capacity * 2);SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newcapacity);if (tmp == NULL){printf("realloc fail\n");exit(-1);//退出程序}psl->a = tmp;psl->capacity = newcapacity;}
}
//尾插
void SeqListPushBack(SL* psl, SLDataType x)
{assert(psl);//psl->a[psl->size] = x;//psl->size++;SLCheckCapacity(psl);//检查扩容psl->a[psl->size++] = x;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, psl->size, x);
}
//尾删
void SeqListPopBack(SL* psl)
{assert(psl);//温柔的处理方式//if (psl->size > 0)//{// psl->size--;//}//else//{// printf("没有数据能够再删了!\n");// exit(-1);//}//暴力的处理方式assert(psl->size > 0);//确保顺序表中有数据psl->size--;//复用pos下标位置删除数据的函数//SeqListErase(psl, psl->size - 1);
}
//头插
void SeqListPushFront(SL* psl, SLDataType x)
{assert(psl);SLCheckCapacity(psl);//挪动数据int end = psl->size -1;while (end >= 0){psl->a[end + 1] = psl->a[end];end--;}psl->a[0] = x;psl->size++;//复用指定pos下标位置插入数据的函数//SeqListInsert(psl, 0, x);
}
//头删
void SeqListPopFront(SL* psl)
{assert(psl);assert(psl->size > 0);//有数据才能删,没数据就会报错int begin = 1;while (begin < psl -> size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;//复用pos效标位置删除数据的函数//SeqListErase(psl, 0);
}
//查找,找到了返回下标,没找到返回-1
int SeqListFind(SL* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; i++){if (psl->a[i] == x){return i;}}return -1;
}
//指定pos下标位置插入数据
void SeqListInsert(SL* psl, int pos, SLDataType x)
{assert(psl);//if (pos > psl->size || pos < 0)//{// printf("pos的下标位置越界");// return;//}//暴力的方式处理(pos下标不能越界)assert(pos >= 0 && pos <= psl->size);//如果没有空间或者空间不足,就扩容SLCheckCapacity(psl);//挪动数据int end = psl->size - 1;while (end >= pos){psl->a[end + 1] = psl->a[end];end--;}psl->a[pos] = x;psl->size++;
}//删除pos位置的数据(结合SeqListFind函数可以删除指定的数据)
void SeqListErase(SL* psl, int pos)
{assert(psl);assert(pos >= 0 && pos < psl->size);//pos位置需要有数据//挪动数据int begin = pos + 1;while (begin < psl->size){psl->a[begin - 1] = psl->a[begin];begin++;}psl->size--;
}//修改pos位置的数据
void SeqListModify(SL* psl, int pos, SLDataType x)
{assert(psl);assert(pos >= 0 && pos < psl->size);psl->a[pos] = x;}
🌴Test.c 文件
#define _CRT_SECURE_NO_WARNINGS 1#include "SeqList.h"int main()
{SL s;SeqListInit(&s);SeqListPushBack(&s, 1);SeqListPushBack(&s, 2);SeqListPushBack(&s, 3);SeqListPushBack(&s, 4);SeqListPushBack(&s, 5);SeqListPushBack(&s, 6);//尾插SeqListPopBack(&s);//尾删SeqListPushFront(&s, 0);//头插SeqListPopFront(&s);//头删SeqListInsert(&s, 2, 8);//指定pos下标为2的位置插入数据8SeqListPrint(&s);//打印SeqListDestroy(&s);//销毁return 0;
}
💨 今天的分享就到这里,如果觉得博主的文章还不错的话, 请👍三连支持一下博主哦🤞
相关文章:

深入解析顺序表:揭开数据结构的奥秘,掌握顺序表的精髓
💓 博客主页:江池俊的博客⏩ 收录专栏:数据结构探索👉专栏推荐:✅C语言初阶之路 ✅C语言进阶之路💻代码仓库:江池俊的代码仓库🔥编译环境:Visual Studio 2022Ἰ…...

数据风险量化评估方案
一、企业面临数据安全的痛点 1、企业缺少清晰的数据安全意识 各部门重视度不够,缺少主动数据安全管控意识。数据安全管控架构不清晰,职责划分不明确。对数据安全管控认识不全面、不深刻。工作人员对于所持有的数据缺乏概念,导致数据的价值无…...

EasyAVFilter代码示例之将视频点播文件转码成HLS(m3u8+ts)视频点播格式
以下是一套完整的视频点播功能开发源码,就简简单单几行代码,就可以完成原来ffmpeg很复杂的视频点播转码调用流程,而且还可以集成在自己的应用程序中调用,例如java、php、cgo、c、nodejs,不需要再单独一个ffmpeg的进程来…...
day-50 代码随想录算法训练营(19)动态规划 part 11
123.买卖股票的最佳时机||| 分析:只能买卖两次,就是说有五个状态: 没有买过第一次买入第一次卖出第二次买入第二次卖出 思路:二维数组,记录五个状态 1.dp存储:dp[i][1] 第一次买入 dp[i][2] 第一次卖…...

自定义权限指令与防止连点指令
1.权限指令 // 注册一个全局自定义权限指令 v-permission Vue.directive(permission, {inserted: function(el, binding, vnode) {const {value} binding; // 指令传的值// user:edit:phone,sysData:sampleconst permissions [user:edit:address, sysData:entrust, sysData:…...

UE5、CesiumForUnreal实现瓦片坐标信息图层效果
文章目录 1.实现目标2.实现过程2.1 原理简介2.2 cesium-native改造2.3 CesiumForUnreal改造2.4 运行测试3.参考资料1.实现目标 参考CesiumJs的TileCoordinatesImageryProvider,在CesiumForUnreal中也实现瓦片坐标信息图层的效果,便于后面在调试地形和影像瓦片的加载调度等过…...
PostgreSQL执行计划
1. EXPLAIN命令 1)PostgreSQL中EXPLAIN命令的语法格式: postgres# \h explain Command: EXPLAIN Description: show the execution plan of a statement Syntax: EXPLAIN [ ( option [, ...] ) ] statement EXPLAIN [ ANALYZE ] [ VERBOSE ] statementwhere option can be…...
【2023 睿思芯科 笔试题】~ 题目及参考答案
文章目录 1. 题目 & 答案单选题编程题问题1:解析1:问题2:解析2: 声明 名称如标题所示,希望大家正确食用(点赞转发评论) 本次笔试题以两种形式考察的,分别是:选择题&a…...
Java手写AVL树
Java手写AVL树 1. AVL树实现思路原理 为了解释AVL树的实现思路原理,下面使用Mermanid代码表示该算法的思维导图: #mermaid-svg-ycH8kKpzVk2HWEby {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid…...

运维自动化:提高效率的秘诀
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

C++设计模式_05_Observer 观察者模式
接上篇,本篇将会介绍C设计模式中的Observer 观察者模式,和前2篇模板方法Template Method及Strategy 策略模式一样,仍属于“组件协作”模式。Observer 在某些领域也叫做 Event 。 文章目录 1. 动机( Motivation)2. 代码…...

github网站打不开,hosts文件配置
首先获取github官网的ip地址, 打开cmd,输入ping github.com 配置: #github 140.82.114.4 github.com 199.232.69.194 github.global.ssl.fastly.net 185.199.108.153 assets-cdn.github.com 185.199.110.153 assets-cdn.github.com 185.199…...
总结PCB设计的经验
一般PCB基本设计流程如下:前期准备->PCB结构设计->PCB布局->布线->布线优化和丝印->网络和DRC检查和结构检查->制版。: : 第一:前期准备。这包括准备元件库和原理图。“工欲善其事,必先利其器”,要做出一…...

HCIE-HCS规划设计搭建
1、相关术语 1、等价路由 等价路由(Equal-cost routing)是一种网络路由策略,用于在网络中选择多个具有相同路由度量(路由距离或成本)的最佳路径之一来转发数据流量。 当存在多个路径具有相同的路由度量时,…...

c语言输出杨辉三角
#include<stdio.h> int main() {int x 0; //表示杨辉三角的的大小int y 1;printf("请输入x的值: ");scanf("%d", &x);for (int i 0; i < x; i) {for (int j 0; j < i; j) {if (j 0 || i 0) {y 1;}else {y y * (i - j 1) / j;}pri…...
性能测试-持续测试及性能测试建设(22)
什么是持续测试? 持续测试定义为:在软件交付流水线中执行自动化测试的过程,目的是获得关于预发布软件业务风险的即时反馈。 完成持续测试,我们还是需要回到定义中,它有3个关键词:软件交付流水线、自动化测试、即时反馈。 首先,持续测试需要具备一条完整的流水线,其代表…...

嵌入式C 语言中的三块技术难点
C 语言在嵌入式学习中是必备的知识,甚至大部分操作系统都要围绕 C 语言进行,而其中有三块技术难点,几乎是公认级别的“难啃的硬骨头”。 今天就来带你将这三块硬骨头细细拆解开来,一定让你看明白了。 0x01 指针 指针是公认…...

【斗破年番】紫研新形象,萧炎终成翻海印,救援月媚,三宗决战
Hello,小伙伴们,我是小郑继续为大家深度解析斗破年番。 斗破苍穹年番动画更新了,小医仙帅气回归,萧炎紫妍成功进入山谷闭关苦修,美杜莎女王守护没多久,就因蛇人族求救离开。从官方公布的最新预告来看,萧炎紫…...

差分方程模型:国民总收入(GDP)的乘数-加速数模型
【背景知识-凯恩斯经济增长模型】 凯恩斯(John M.Keynes)建立了著名的国民经济增长模型。令Y表示国民总收入,C表示总消费,E为总支出,I表示投资,G为政府的投入(如基建等)。那么有 【6.1】 其中࿰…...

【C语言】指针和数组笔试题解析(1)
指针是C语言的灵魂,他的玩法多种多样,这篇文章带来指针的笔试题详解,可以帮助我们更好的理解与巩固指针的知识 目录 预备知识:题目:一维数组:二维数组: 题目比较多,但切记戒骄戒躁&a…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...