数据结构:手撕代码——顺序表

目录

 

1.线性表

2.顺序表

2.1顺序表的概念

2.2动态顺序表实现

 2.2-1 动态顺序表实现思路

2.2-2 动态顺序表的初始化

 2.2-3动态顺序表的插入

检查空间

 尾插

头插 

中间插入 

2.2-4 动态顺序表的删除 

尾删

头删 

中间删除 

2.2. 5 动态顺序表查找与打印、销毁

查找

打印 

销毁 

 2.2 6 测试动态顺序表


1.线性表

    线性表(linear list)是n个具有相同特性的数据元素的有限序列。例如我们有一个数组,这个数组中的元素都占相同大小的内存,都具有相同的类型,而它们也按顺序排列的。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

     线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。什么意思呢?逻辑结构可以看作我们把它想象成一个排列有序的数组:

  

物理结构就是这个表实际在内存的结构,它有可能是一个排列有序的数组,但是更大的可能是用指针连起来的无序的一块块空间:

2.顺序表

2.1顺序表的概念

    顺序表是线性表的其中一种。它是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

顺序表一般可以分为:
1. 静态顺序表:使用定长数组存储元素。

2. 动态顺序表:使用动态开辟的数组存储。

     那么二者哪个更具有优势呢?答案是动态顺序表,如果我们使用静态顺序表去存储某个app的用户数据,那么我们该用多少空间呢,如果空间太少,我们就会丢失一部分用户的数据,如果空间太大,又会浪费内存,而使用动态顺序表则不用考虑这两个问题,如果我们空间太小就增加内存,而一开始我们不会开辟太大的内存,所以不用担心空间浪费的问题,所以我们本期就要用代码实现动态顺序表。

2.2动态顺序表实现

  我们要实现顺序表,需要实现它的增删查改等功能:

typedef int SLDataType;
// 顺序表的动态存储
typedef struct SeqList
{
SLDataType* array; // 指向动态开辟的数组
size_t size ;
// 有效数据个数
size_t capicity ;
// 容量空间的大小
}SeqList;
// 基本增删查改接口
// 顺序表初始化
void SeqListInit(SeqList* psl);
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl);
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SeqList* psl);
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x);
// 顺序表头删
void SeqListPopFront(SeqList* psl);
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);
// 顺序表销毁
void SeqListDestory(SeqList* psl);
// 顺序表打印
void SeqListPrint(SeqList* psl)

接下来我们来一个一个实现吧。

 2.2-1 动态顺序表实现思路

    我们需要实现顺序表的增删查改等功能,包含十几个方法,为了避免代码混乱等问题,我们将顺序表分成三个文件来实现(1)test.c,这个文件负责我们实现接口之后的测试,(2)SeqList.h,这个文件负责包含所有头文件和放置所有的函数声明,如果另外两个文件要使用这些头文件只需要包含这个文件就可以了,(3)SeqList.h,这个文件负责实现所有方法(函数)的功能,我们顺序表的大部分代码也是在这个文件。

2.2-2 动态顺序表的初始化

     有了思路之后我们就来实现我们的代码。首先我们创建三个文件:

在SeqList文件中包含我们要用到的头文件,输入输出需要用到stdio.h,开辟内存的函数需用到stdlib.h,我们还会用到断言(assert.h),为了避免多次包含头文件以免不必要的内存浪费,我们还会用到#pragma once 这段代码:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

接下来我们创建一个顺序表,我们用一个结构体来表示这个顺序表并用typedef将它更名为SL:

typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效数据int capacity;//空间大小}SL;

那么存储数据的类型为什么也要改名呢?因为我们将来如果使用顺序表存储数据时,我们并不知道我们存何种类型的数据,如果我们存储的数据是int,而要将它们全部换成字符类型,此时恰好我们已经写了100000行代码,我们要修改的化会变得相当困难,所以我们将数据类型改名是为了方便以后我们要存储不同类型数据时可以很方便的更换类型。

我们来实现第一个方法——初始化,在开始时我们将它们都初始化为0:

void SeqInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}//初始化
 2.2-3动态顺序表的插入

    我们使用顺序表最主要的功能就是存储数据,而在一开始顺序表是没有数据的,所以我们先实现插入功能,插入分为:尾插,头插,从中间插入。尾插就是在最后一个有效数据后插入我们要插入的数据:

例如这个顺序表有三个有效数据,那么我们的尾插就是将它放在最后一个有效数据(3)的后面,如果我们将数字4用尾插的方式插入顺序表,那么就是这样:

头插则与尾插刚好相反,它是将要插入的数据放在有效数据的最前面,而使其他数据整体往后移一位,假设我们要用头插插入数字0:

使用中间插入我们可以指定插入的位置,如果我们要将数字6插入到3的位置,我们只需要将这个位置后的所有有效数据都往后挪一位:

接下来我们用代码实现。

检查空间

       使用插入前,我们需要为顺序表开辟一块空间,我们在空间上会遇到两个问题:如果我们是第一次进来,所有数据都为0,那么我们要第一次开辟内存;如果我们要存入数据时,内存不足,则需要新开辟内存。这两种情况都有一个共同点——有效数据与空间大小相等,所以只要有序数据和空间大小相等时我们就增加1倍空间,在进入函数时,我们先判断这个指针是不是为空,如果我们向空指针存入数据,则一点会出错,代码实现:

void SeqCheckcapa(SL* ps)//检查内存够不够,不够则增加
{assert(ps);if (ps->capacity == ps->size){int Newcapecity = ps->capacity == 0 ? 4 : 2 * ps->capacity * sizeof(SLDataType);SLDataType* tem = (SLDataType*)realloc(ps->arr, Newcapecity * 2 *sizeof(SLDataType));if (tem != NULL){ps->arr = tem;}}
}
 尾插

  我们使用尾插前先判断我们的空间够不够,传入的指针是否为空。那么我们如何插入呢?我们顺序表中的有效数据是size个,而最后一个有效数据的下标是size-1,我们只需要在下标为size的位置插入数据,然后size加1,就完成了尾插的操作:

void SeqPushBack(SL* ps, SLDataType x)
{assert(ps);SeqCheckcapa(ps);ps->arr[ps->size++] = x;}//尾插

画图演示:

头插 

  头插前面做的事和尾插一样,先判断指针是不是为空,再判断空间够不够。然后将所有数据往后移一位,最后在下标为0的位置插入数据,size加1:

void SeqPushFront(SL* ps, SLDataType x)
{assert(ps);SeqCheckcapa(ps);int i = 0;for (i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];} ps->arr[0] = x;++ps->size;
}//头插
中间插入 

先判断指针是否为空和判断空间够不够。因为中间插入是指定位置进行插入,所以我们只能在已经有的数据中间插入,我们指定的数字不能小于0,也不能大于size。当我们指定了一个有效数字pos下标,我们将这个位置及它后面的所有数据往后挪一位,此时这个位置就空出来了,我们也就可以插入我们想插入的数字,插入之后,我们让size加1:

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SeqCheckcapa(ps);int i = 0;for (i = ps->size ; i>pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;++ps->size;}//指定下标前插入数据

2.2-4 动态顺序表的删除 

删除同样分为尾删,头删,中间删除,这部分内容比插入相对简单一点。

尾删

 我们先判断指针是否为空,再判断有效数据的情况,如果有效数据为0,我们就不能删除数据。而删除数据,只需要让size往前挪动一位,我们打印时不会打印这个数据,而插入数据时会将这个数据覆盖:

void SeqPopBack(SL* ps)
{assert(ps);assert(ps->size >= 0);ps->size--;
}//尾删
头删 

与尾删一样,先判断指针是否为空,再判断数据情况。头删操作只需将第二位及后面的所以数据往前移动一位,将第一位数据覆盖,最后让size减1就可以了:

代码实现:

void SeqPopFront(SL* ps)
{assert(ps);assert(ps->size >= 0);int i = 0;for (i = 0; i <ps->size-1 ; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}//头删
中间删除 

  先判断指针是否为空,再判断有效数据的情况。因为中间删除是指定位置删除,那么这个制定的数字肯定不能小于0,也不能大于等于size,而删除操作与头删相似,我们指定好数字后,只需要将它后面的所有有效数据往前挪动一位将它覆盖然后让size减1就可以了:

void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int i = 0;for (i = pos; i<ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//指定下标删除

2.2. 5 动态顺序表查找与打印、销毁

查找

查找数据我们先判断指针是否为空。使用循环判断顺序表中是否有我们要查找的数据,如果找到了,则返回它的下标,如果找不到,则返回-1:

int SLFind(SL* ps, SLDataType x)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1;
}//查找数据

我们使用一个整型来接收,如果大于0,说明找到了,并打印它的下标,如果小于0,则表示顺序表中没有这个数据:

int find = SLFind(&sl, 4);
if (find < 0)
{printf("没有找到!\n");
}
else
{printf("找到了,下标是%d\n", find);
}
打印 

打印顺序表中的数据要先判断指针是否为空。接着使用循环将它的内容打印出来:

void SeqPrint(SL* ps)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}//打印
销毁 

 当使用完这块动态开辟出来的空间,不要忘了释放,以免造成内存泄漏和出现野指针的情况:

void SeqDestroy(SL* ps)
{assert(ps);free(ps->arr);if (ps->arr != NULL);{ps->arr = NULL;}ps->capacity = ps->size = 0;
}
//销毁

至此所有方法就实现完成了。 

 2.2 6 测试动态顺序表

  我们来测试一下其中一些方法:

void test2()
{SL sl;SeqInit(&sl);//插入1 2 3 4SeqPushBack(&sl, 1);SeqPushBack(&sl, 2);SeqPushBack(&sl, 3);SeqPushBack(&sl, 4);SeqPrint(&sl);//插入99 99SLInsert(&sl, 0, 99);SLInsert(&sl, 3, 88);SLInsert(&sl, sl.size, 10000);SeqPrint(&sl);//删除SLErase(&sl,2);SeqPrint(&sl);SLErase(&sl, 5);SeqPrint(&sl);//查找int find = SLFind(&sl, 4);if (find < 0){printf("没有找到!\n");}else{printf("找到了,下标是%d\n", find);}//释放空间SeqDestroy(&sl);
}

来看运行结果:

可以看到我们实现的方法都没有问题,我将原码放在下面,感兴趣的小伙伴可以试试哦。

SeqList.h :

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int SLDataType;
typedef struct SeqList
{SLDataType* arr;int size;//有效数据int capacity;//空间大小}SL;void SeqInit(SL* ps);//初始化void SeqDestroy(SL* ps);//销毁void SeqPushBack(SL* ps, SLDataType x);//尾插void SeqPushFront(SL* ps, SLDataType x);//头插void SeqPopBack(SL* ps);//尾删void SeqPopBack(SL* ps);//头删void SeqPrint(SL* ps);//打印void SLErase(SL* ps, int pos);//指定删除int SLFind(SL* ps, SLDataType x);//查找数据//指定下标前插入数据
void SLInsert(SL* ps,int pop, SLDataType x);

SeqList.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"void SeqInit(SL* ps)
{ps->arr = NULL;ps->size = ps->capacity = 0;
}//初始化void SeqCheckcapa(SL* ps)//检查内存够不够,不够则增加
{assert(ps);if (ps->capacity == ps->size){int Newcapecity = ps->capacity == 0 ? 4 : 2 * ps->capacity * sizeof(SLDataType);SLDataType* tem = (SLDataType*)realloc(ps->arr, Newcapecity * 2 *sizeof(SLDataType));if (tem != NULL){ps->arr = tem;}}
}void SeqPushBack(SL* ps, SLDataType x)
{assert(ps);SeqCheckcapa(ps);ps->arr[ps->size++] = x;}//尾插void SeqPushFront(SL* ps, SLDataType x)
{assert(ps);SeqCheckcapa(ps);int i = 0;for (i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];} ps->arr[0] = x;++ps->size;
}//头插void SeqPopBack(SL* ps)
{assert(ps);assert(ps->size >= 0);ps->size--;
}//尾删void SeqPopFront(SL* ps)
{assert(ps);assert(ps->size >= 0);int i = 0;for (i = 0; i <ps->size-1 ; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;}//头删void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SeqCheckcapa(ps);int i = 0;for (i = ps->size ; i>pos; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[pos] = x;++ps->size;}//指定下标前插入数据void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);int i = 0;for (i = pos; i<ps->size-1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}//指定下标删除int SLFind(SL* ps, SLDataType x)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){if (ps->arr[i] == x){return i;}}return -1;
}//查找数据
void SeqPrint(SL* ps)
{assert(ps);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ", ps->arr[i]);}printf("\n");
}//打印void SeqDestroy(SL* ps)
{assert(ps);free(ps->arr);if (ps->arr != NULL);{ps->arr = NULL;}ps->capacity = ps->size = 0;
}
//销毁

test.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
//void SLPushBack(SL* ps, SLDatatype x)
//{
//	assert(ps);
//
//	if (ps->size == ps->capacity)
//	{
//		int Newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
//
//		SLDatatype* tem=(SLDatatype*)realloc(ps->arr,2* Newcapacity*sizeof(SLDatatype))
//			if (tem == NULL)
//			{
//				perror("realloc");
//				exit(1);
//			}
//
//		ps->arr = tem;
//		ps->capacity = Newcapacity;
//	}
//	ps->arr[size++] = x;
//
//}
//
//
//
//
//void SLPushBack(SL* ps, SLDataType x)
//{
//	//1.判断指针是否为空,为空则出错
//	assert(ps);
//
//	//2.判断空间够不够,不够则申请空间
//	if (ps->capecity == ps->size)
//	{
//		//如果capecity为0,我们就要第一次开辟出4个SLDataType类型的空间
//		SLDataType NewCapecity = ps->capecity == 0 ? 4 : 2 * ps->capecity;
//		//开辟空间,如果下次空间不够,则下次开辟此次2倍的空间
//		SLDataType* tem = (SLDataType*)realloc(ps->arr, NewCapecity * 2 * sizeof(SLDataType));
//		if (tem == NULL)
//		{
//			perror("realloc");
//			exit(1);
//		}
//		//走到这里说明tem不为空,将新开辟好的内存给arr
//		ps->arr = tem;
//		ps->capecity = NewCapecity;
//	}
//	ps->arr[ps->size++] = x;
//	//3.进行尾插操作
//}
void test1()
{SL sl;SeqInit(&sl);SeqPushBack(&sl, 1);SeqPushBack(&sl, 2);SeqPushBack(&sl, 3);SeqPushBack(&sl, 4);SeqPrint(&sl);SeqPushFront(&sl, 6);SeqPrint(&sl);SeqPopBack(&sl);SeqPrint(&sl);SeqPopFront(&sl);SeqPopFront(&sl); SeqPopFront(&sl); SeqPrint(&sl);SeqDestroy(&sl);
}
void test2()
{SL sl;SeqInit(&sl);//插入1 2 3 4SeqPushBack(&sl, 1);SeqPushBack(&sl, 2);SeqPushBack(&sl, 3);SeqPushBack(&sl, 4);SeqPrint(&sl);//插入99 99SLInsert(&sl, 0, 99);SLInsert(&sl, 3, 88);SLInsert(&sl, sl.size, 10000);SeqPrint(&sl);//删除SLErase(&sl,2);SeqPrint(&sl);SLErase(&sl, 5);SeqPrint(&sl);//查找int find = SLFind(&sl, 4);if (find < 0){printf("没有找到!\n");}else{printf("找到了,下标是%d\n", find);}//释放空间SeqDestroy(&sl);
}
int main()
{test2();//test1();return 0;
}

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

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

相关文章

mysql导入sql文件失败及解决措施

1.报错找不到表 1.1 原因 表格创建失败&#xff0c;编码问题mysql8相较于mysql5出现了新的编码集 1.2解决办法&#xff1a; 使用vscode打开sql文件ctrlh&#xff0c;批量替换&#xff0c;替换到你所安装mysql支持的编码集。 2.timestmp没有设置默认值 Error occured at:20…

一个公用的数据状态修改组件

灵感来自于一项重复的工作&#xff0c;下图中&#xff0c;这类禁用启用、审核通过不通过、设计成是什么状态否什么状态的场景很多。每一个都需要单独提供接口。重复工作还蛮大的。于是&#xff0c;基于该组件类捕获组件跳转写了这款通用接口。省时省力。 代码如下&#xff1a;…

Linux开机自启/etc/init.d和/etc/rc.d/rc.local

文章目录 /etc/init.d和/etc/rc.d/rc.local的区别/etc/init.dsystemd介绍 /etc/init.d和/etc/rc.d/rc.local的区别 目的不同&#xff1a; /etc/rc.d/rc.local&#xff1a;用于在系统启动后执行用户自定义命令&#xff0c;适合简单的启动任务。 /etc/init.d&#xff1a;用于管理…

实现一个vue js小算法 选择不同的时间段 不交叉

以上图片选择了时间段 现在需要判断 当前选择的时间段 不能够是 有交叉的所以现在需要循环判断 //判断时间段是否重叠交叉 export function areIntervalsNonOverlapping(intervals:any) {// 辅助函数&#xff1a;将时间字符串转换为从当天午夜开始计算的分钟数function conver…

信息系统架构风格-系统架构师(十

1、信息系统架构风格是描述特定应用领域中系统组织方式的惯用模式。架构风格定义了一个系统家族&#xff0c;即一个架构定义&#xff08;&#xff09;。 A一组设计原则 B一组模式 C一个词汇表和一组约束 D一组最佳实践 解析&#xff1a; 信息系统架构风格是描述某一特定 应…

汽车金属管检测新方法,分度盘高速视觉检测机检测效果如何?

汽车金属管是指在汽车制造和维修中广泛使用的金属管道&#xff0c;用于传输流体、气体或其他介质。汽车金属管在汽车中扮演着重要的角色&#xff0c;用于传输液体&#xff08;如燃油、冷却液、润滑油&#xff09;、气体&#xff08;如空气、排气&#xff09;、制动系统、液压系…

详解函数动态调用的作用——call

动态调用的作用 类似于其他语言的反射能够开发框架性代码 Call调用语法 (bool success, bytes data) <address>.call(bytes calldata)call是address的方法call返回值(bool success, bytes data)忽视返回值success&#xff0c;会造成严重问题 calldata的结构 call的…

183.二叉树:二叉搜索树中的众数(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

Linux2(文件类型分类 基本命令2 重定向)

目录 一、文件类型分类 二、基本命令2 1. find 帮助查询 2. stat 查看文件的信息 3. wc 统计文本 4. 查看文本内容 4.1 cat 4.2 more 4.3 less 4.4 head 4.5 tail 5. cal 显示日历 6. date 显示时间 7. du 文件大小 8. ln 链接 软链接 硬链接 区别 9. histo…

碳中和研究院OLED透明屏2x2整机项目方案

一、项目背景 随着全球气候变化和环境问题的日益严重&#xff0c;碳中和成为各国政府和企业的重要议题。为了响应这一趋势&#xff0c;黑龙江碳中和研究院计划引入先进的OLED透明屏技术&#xff0c;以展示其研究成果和碳中和理念。本项目旨在为该研究院提供一套高质量的OLED透明…

关于Mysql 中 Row size too large (> 8126) 错误的解决和理解

提示&#xff1a;啰嗦一嘴 &#xff0c;数据库的任何操作和验证前&#xff0c;一定要记得先备份&#xff01;&#xff01;&#xff01;不会有错&#xff1b; 文章目录 问题发现一、问题导致的可能原因1、页大小2、行格式2.1 compact格式2.2 Redundant格式2.3 Dynamic格式2.4 Co…

vmmare虚拟机没有被分配ip地址问题;NAT模式下一直变化问题

打开任务管理器–>服务–>找到与VM和server相关的服务 发现NAT和DHCP服务被关闭了 尝试启动&#xff0c;报错 尝试一 虚拟网络编辑器点击还原默认设置 尝试二 可以了 ip变化 更改租用时长

性能测试常见的内存溢出问题: JVM 内存溢出如何调优?

针对java项目做性能测试的时候,很多同学都见过一个报错,就是OOM【Out Of MemoryError】;那出现这种报错就是项目发生了内存溢出的问题,这是比较严重的性能问题。所以,作为一个性能测试工程师,我们要能够分析JVM内存的问题以及理解其中的原理,才能更好的给JVM内存出现的性…

Wireless Network(百练,POJ)

题目链接: http://bailian.openjudge.cn/tm2019/F/ 2236 -- Wireless Network 题面描述: 思路: 这题开了10s&#xff0c;所以可以暴力点&#xff0c;每次修复一个点&#xff0c;就将该点相连的那些边建出来&#xff0c;总的时间复杂度为: O(nm)。关键在于如何判定两个点是否…

新能源汽车不安全?新能源汽车测试之方案篇——充电桩综合测试

背景 随着全球对气候变化和环境污染问题的日益加剧&#xff0c;新能源汽车作为一种环保、节能的交通工具备受关注。其发展背景主要源于对环境问题的关注以及对传统燃油汽车依赖的减少。新能源汽车的出现&#xff0c;带来了减少尾气排放、节能减排、保护环境等多方面的优点&…

【STM32】uc/OS-III多任务程序

目录 一、背景介绍二、UCOS-III简单介绍&#xff08;一&#xff09;源码&#xff08;二&#xff09;功能 三、实验&#xff08;一&#xff09;基于STM32CubeMX建立工程1、创建项目2、配置项目 &#xff08;二&#xff09;实现 四、总结五、参考 一、背景介绍 学习嵌入式实时操…

《精通ChatGPT:从入门到大师的Prompt指南》第7章:创意写作

第7章&#xff1a;创意写作 7.1 角色设定 角色设定是创意写作中最关键的环节之一。成功的角色设定能够让读者对故事产生共鸣&#xff0c;使故事更加生动有趣。角色不仅仅是情节发展的载体&#xff0c;更是读者情感的投射对象。因此&#xff0c;深入了解如何设定一个生动而有深…

【React】json-server

1.安装到开发环境 npm install json-server -D2.在根目录下下&#xff0c;新建db.json文件 {"list": [{"rpid": 3,"user": {"uid": "13258165","avatar": "http://toutiao.itheima.net/resources/images/9…

Go Module详解

文章目录 基本介绍相关环境变量Go Module的使用初始化项目&#xff08;go mod init&#xff09;管理依赖项&#xff08;go mod edit&#xff09;获取依赖项&#xff08;go mod download&#xff09;整理依赖项&#xff08;go mod tidy&#xff09;导入vendor目录&#xff08;go…

【DevOps】Ubuntu基本使用教程

目录 引言 Ubuntu简介 安装Ubuntu 准备工作 创建启动盘 安装过程 桌面环境 基本操作 定制桌面 文件管理 文件操作 文件权限 软件管理 安装软件 更新软件 系统设置 用户账户 网络设置 电源管理 命令行操作 常用命令 管理权限 安全与维护 系统更新 备份…