【数据结构】详解线性表的各个函数接口+OJ习题讲解(画图比写代码更重要!!!)

文章目录

    • 一、线性表
    • 二、顺序表
      • 1、什么是顺序表
      • 2、顺序表的分类
    • 三、动态顺序表的实现
      • 1、结构的定义
      • 2、顺序表的初始化
      • 3、检查容量
      • 4、在头部插入数据
      • 5、在尾部插入数据
      • 6、在指定位置插入数据
      • 7、在尾部删除数据
      • 8、在头部删除数据
      • 9、删除指定位置的数据
      • 10、查找数据
      • 11、修改指定位置的数据
      • 12、打印顺序表中的数据
      • 13、顺序表的销毁
    • 四、完整代码
      • 1、SeqLIst.h
      • 2、SeqList.c
      • 3、test.c
    • 五、顺序表的缺陷
    • 六、顺序表力扣OJ题
      • 1、移除元素
        • 思路1
        • 思路2
        • 思路3
      • 2、删除有序数组中的重复项
      • 3、合并两个有序数组

一、线性表

是什么线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列; 线性表是一种在实际中广泛使 用的数据结构,常见的线性表有:顺序表、链表、栈、队列、字符串…

线性表的结构

线性表在逻辑上是线性结构,也就说是连续的一条直线;但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。

本篇文章,我们先讲解数组形式存储结构存储的线性表!
image-20220728153107491


二、顺序表

1、什么是顺序表

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

简单来说,顺序表就是数组,只是要求数组里面的元素必须连续存储而已。

2、顺序表的分类

顺序一般分为两类:静态顺序表和动态顺序表。

静态顺序表:采用定长数组来存储元素。(一般不考虑)

#define MAX 1000 //数组的最大长度 typedef int SLDtataType; //重命名数据类型 typedef struct SeqList { SLDtataType data[MAX]; //使用定长数组来存储数据 size_t size; //有效数据的个数 }SL;

动态顺序表:使用动态开辟的数据来存储元素。(重点 有三个元素组成)

typedef int SLDataType; //将数据类型重命名为SLDataType 
typedef struct SeqList { SLDataType* data; //对应数据类型的指针,用来指向动态开辟的空间 size_t size; //记录当前有效数据的个数 size_t capacity; //记录当前容量,不够就增容 
}SL;

两种顺序表的对比:相较于动态顺序表,静态顺序表存在很大的缺陷,那就是空间问题:当我们数据量很大时给定的空间可能不够用,但我们数据量比较小时,给定的空间又可能过大,造成空间浪费,即静态顺序表只适用于确定知道需要存多少数据的场景;所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,而静态顺序表很少使用。下面我们用C语言来模拟实现一个动态的顺序表。


三、动态顺序表的实现

1、结构的定义

#define DEF_SIZE 5 //初始容量 
#define CRE_SIZE 2 //一次扩容的倍数 
typedef int SLDataType; //将数据类型重命名为SLDataType 
typedef struct SeqList { SLDataType* data; //对应数据类型的指针,用来指向动态开辟的空间 size_t size; //记录当前有效数据的个数 size_t capacity; //记录当前容量,不够就增容 
}SL;

如上:我们将要管理的数据类型重命名为SLDateType,这样以后当我们要用此顺序表管理其他数据类型时,我们就只需要改动这一个地方。

其次,相较于静态顺序表,我们的结构体多了一个参数 – capacity,我们用它来记录顺序表当前的容量,当当前的有效数据个数size与它相等时,我们就进行扩容;由于数据个数和顺序表的容量都不可能小于0,所以我们将其定义为size_t的。

最后就是关于初始容量和每次扩增倍数的问题,这里把初始容量设定为5,然后把扩增倍数设定为2,即我们的顺序表每次扩容两倍。

2、顺序表的初始化

在初始化函数中,我们把size和capacity都置为相应大小,并且为data指针动态开辟一块空间,用于存储数据。

void SLInit(SL* psl)
{assert(psl);psl->a = NULL;psl->capacity = psl->size = 0;
}

3、检查容量

在检查容量的函数中,当我们结构体中的size和capacity相等时,我们就扩容,在扩容时我们要注意不要直接用data指针来接收realloc函数的返回值,避免扩容失败导致data指针找不到之前管理的空间,从而造成内存泄漏。

void SLCheckCapacity(SL* psl)
{// 检查容量if (psl->size == psl->capacity){int newCapcity = psl->capacity == 0 ? 4 : psl->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(psl->a, newCapcity*sizeof(SLDataType));if (tmp == NULL){perror("realloc fail");return;//exit(-1);}psl->a = tmp;psl->capacity = newCapcity;}}

这里realloc有一个知识点:
在这里插入图片描述

在这里插入图片描述

我们realloc 后面写的是个数*sizeof(SLDatatype) 而不是单纯的个数 因为我们开辟的是空间大小

4、在头部插入数据

在头部插入数据时,我们需要先将顺序表中的数据整体向后挪动一位,然后在顺序表的开头插入;在插入完成后记得要让size++。

void SLPushFront(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++;
}

5、在尾部插入数据

在尾部插入数据很简单,直接插入就行。

void SLPushBack(SL* psl, SLDataType x)
{assert(psl);SLCheckCapacity(psl);psl->a[psl->size] = x;psl->size++;
}

6、在指定位置插入数据

在此函数中,我们需要先将pos及其之后的元素整体向后挪动一位,然后再在pos处插入数据。

//void SLInsert(SL* psl, int pos, SLDataType x)
void SLInsert(SL* psl, size_t pos, SLDataType x)
{assert(psl);assert(pos <= psl->size);SLCheckCapacity(psl);// 挪动数据/*int end = psl->size - 1;while (end >= (int)pos){psl->a[end + 1] = psl->a[end];--end;}*/size_t end = psl->size;while (end > pos){psl->a[end] = psl->a[end-1];--end;}psl->a[pos] = x;++psl->size;
}

由于尾插和头插也可以通过调用 SeqListInsret 函数实现,所以我们可以对头插和尾插函数进行改造,以此来简化代码:

在头部插入数据

void SLPushFront(SL* psl, SLDataType x)
{SLInsert(psl, 0, x);
}

在尾部插入数据

void SLPushBack(SL* psl, SLDataType x)
{SLInsert(psl, psl->size, x);
}

7、在尾部删除数据

删除尾部的数据很简单,我们只需要将size–即可,并不需要对其进行改动,因为我们下一次插入数据时会直接将原来空间中的数据覆盖掉。

void SLPopBack(SL* psl)
{//assert(psl); 温柔的检查///*if (psl->size == 0)//{//return;//}*/ 暴力的检查//assert(psl->size > 0);//psl->size--;SLErase(psl, psl->size - 1);
}

8、在头部删除数据

在头部删除数据,我们只需要将顺序表中的数据整体向前挪动一位,然后将size–即可。

void SLPopFront(SL* psl)
{//assert(psl);//assert(psl->size > 0);///*int begin = 0;//while (begin < psl->size-1)//{//	psl->a[begin] = psl->a[begin + 1];//	++begin;//}*///int begin = 1;//while (begin < psl->size)//{//	psl->a[begin-1] = psl->a[begin];//	++begin;//}//--psl->size;SLErase(psl, 0);
}

9、删除指定位置的数据

删除指定位置数据,我们需要将pos后面的数据整体向前挪动一位,然后让size–。

void SLErase(SL* psl, size_t pos)
{assert(psl);assert(pos < psl->size);size_t begin = pos;while (begin < psl->size - 1){psl->a[begin] = psl->a[begin + 1];++begin;}psl->size--;
}

和上面的插入数据一样,我们也可以通过调用 SeqListErase 函数来实现数据的头删和尾删。


**面试题:删除数据是否要缩容?**我们知道,插入数据空间不够时我们要增容,那么删除数据达到一定的数量后我们是否要缩容呢?答案是不用缩容。原因如下:第一:我们缩容之后插入数据又需要重新增容,而增容是有代价的,会降低程序的效率。我们知道 realloc 函数扩容分为两种情况,一种是原地扩,即当原来的空间后面有足够的空闲空间时,操作系统会直接将那一块空间交由我们使用,这种情况对效率影响不大;另一种是异地扩,即当原来空间后面没有足够的的空间开辟时,操作系统会在另外空间足够的地方为我们开辟一块新的空间,这时操作系统需要先将我们原来空间中的数据拷贝到新空间中,再将原来的空间释放掉,这种情况对效率的影响就比较大了。第二:缩容也是有代价的。其实缩容和扩容的过程是一样的,都分为原地和异地,会对程序效率造成影响。第三:顺序表申请的是一块连续的空间,而free函数数并不能释放连续空间的一部分,只能全部一起释放,所以这里即使想释放也是做不到的。所以综合前面三个因素考虑,顺序表删除数据不会缩容;这是我们典型的**以空间换时间**的做法。

10、查找数据

当我们找到该元素时,我们返回元素的下标;当该元素不存在时,我们返回一个无意义的值。(如-1)

int SLFind(SL* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; ++i){if (psl->a[i] == x){return i;}}return -1;
}

11、修改指定位置的数据

void SLModify(SL* psl, size_t pos, SLDataType x)
{assert(psl);assert(pos < psl->size);psl->a[pos] = x;
}

12、打印顺序表中的数据

void SLPrint(const SL* psl)
{assert(psl);for (int i = 0; i < psl->size; ++i){printf("%d ", psl->a[i]);}printf("\n");
}

13、顺序表的销毁

在销毁顺序表的时候我们一定要记得将前面动态开辟的空间释放掉,防止内存泄漏。

void SLDestory(SL* psl)
{assert(psl);/*if (psl->a){*/free(psl->a);psl->a = NULL;psl->capacity = psl->size = 0;//}
}

四、完整代码

1、SeqLIst.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>//#ifndef __SEQLIST_H__
//#define __SEQLIST_H__
...
//#endif// Shunxubiao -- 二狗  铁柱  招弟// 静态的顺序表 -- 不知道要存储多少数据?
//#define N 10000
//typedef int SLDataType;
//struct SeqList
//{
//	SLDataType a[N];
//	int size; // 存储数据的个数
//};// 动态顺序表
typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;      // 存储数据的个数int capacity;  // 存储空间的大小
}SL;//void SeqListInit(SL sl);
void SLInit(SL* psl);
void SLDestory(SL* psl);
void SLPrint(const SL* psl);// 头插头删 尾插尾删
void SLPushBack(SL* psl, SLDataType x);
void SLPushFront(SL* psl, SLDataType x);
void SLPopBack(SL* psl);
void SLPopFront(SL* psl);// 没有找到就返回-1
int SLFind(SL* psl, SLDataType x);// 顺序表在pos位置插入x
void SLInsert(SL* psl, size_t pos, SLDataType x);// 顺序表删除pos位置的值
void SLErase(SL* psl, size_t pos);void SLModify(SL* psl, size_t pos, SLDataType x);

2、SeqList.c

#include "SeqList.h"void SLPrint(const SL* psl)
{assert(psl);for (int i = 0; i < psl->size; ++i){printf("%d ", psl->a[i]);}printf("\n");
}void SLInit(SL* psl)
{assert(psl);psl->a = NULL;psl->capacity = psl->size = 0;
}void SLDestory(SL* psl)
{assert(psl);/*if (psl->a){*/free(psl->a);psl->a = NULL;psl->capacity = psl->size = 0;//}
}void SLCheckCapacity(SL* psl)
{// 检查容量if (psl->size == psl->capacity){int newCapcity = psl->capacity == 0 ? 4 : psl->capacity * 2;SLDataType* tmp = (SLDataType*)realloc(psl->a, newCapcity*sizeof(SLDataType));if (tmp == NULL){perror("realloc fail");return;//exit(-1);}psl->a = tmp;psl->capacity = newCapcity;}}// https://cplusplus.com/reference/
void SLPushBack(SL* psl, SLDataType x)
{/*assert(psl);SLCheckCapacity(psl);psl->a[psl->size] = x;psl->size++;*/SLInsert(psl, psl->size, x);
}void SLPushFront(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++;SLInsert(psl, 0, x);
}void SLPopBack(SL* psl)
{//assert(psl); 温柔的检查///*if (psl->size == 0)//{//return;//}*/ 暴力的检查//assert(psl->size > 0);//psl->size--;SLErase(psl, psl->size - 1);
}void SLPopFront(SL* psl)
{//assert(psl);//assert(psl->size > 0);///*int begin = 0;//while (begin < psl->size-1)//{//	psl->a[begin] = psl->a[begin + 1];//	++begin;//}*///int begin = 1;//while (begin < psl->size)//{//	psl->a[begin-1] = psl->a[begin];//	++begin;//}//--psl->size;SLErase(psl, 0);
}int SLFind(SL* psl, SLDataType x)
{assert(psl);for (int i = 0; i < psl->size; ++i){if (psl->a[i] == x){return i;}}return -1;
}//void SLInsert(SL* psl, int pos, SLDataType x)
void SLInsert(SL* psl, size_t pos, SLDataType x)
{assert(psl);assert(pos <= psl->size);SLCheckCapacity(psl);// 挪动数据/*int end = psl->size - 1;while (end >= (int)pos){psl->a[end + 1] = psl->a[end];--end;}*/size_t end = psl->size;while (end > pos){psl->a[end] = psl->a[end-1];--end;}psl->a[pos] = x;++psl->size;
}// 顺序表删除pos位置的值
void SLErase(SL* psl, size_t pos)
{assert(psl);assert(pos < psl->size);size_t begin = pos;while (begin < psl->size - 1){psl->a[begin] = psl->a[begin + 1];++begin;}psl->size--;
}void SLModify(SL* psl, size_t pos, SLDataType x)
{assert(psl);assert(pos < psl->size);psl->a[pos] = x;
}

3、test.c

//#include <stdio.h>
//#include <stdlib.h>
//
//void f1(int n)
//{
//	int a = 0;
//	int* p = (int*)malloc(4 * n);
//
//	printf("%p,%p\n", &a, &p);
//	if(p == NULL)
//	{
//		perror("malloc fail");
//		return;
//	}
//
//	free(p);
//}
//
 2N+2 个数
 N+1  个数
//int main()
//{
//	f1(10);
//	f1(10);
//
//	return 0;
//}
#include "SeqList.h"void TestSeqList1()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPushBack(&s, 5);SLPushBack(&s, 6);SLPrint(&s);SLPushFront(&s, 10);SLPushFront(&s, 20);SLPushFront(&s, 30);SLPrint(&s);SLDestory(&s);
}void TestSeqList2()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPrint(&s);SLPopBack(&s);SLPopBack(&s);SLPrint(&s);SLPopBack(&s);SLPopBack(&s);SLPrint(&s);//SLPopBack(&s);//SLPrint(&s);SLPushBack(&s, 10);SLPushBack(&s, 20);SLPushBack(&s, 30);SLPushBack(&s, 40);SLPrint(&s);SLDestory(&s);
}void TestSeqList3()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPrint(&s);SLPopFront(&s);SLPopFront(&s);SLPrint(&s);SLPopFront(&s);SLPopFront(&s);SLPrint(&s);SLPushBack(&s, 10);SLPushBack(&s, 20);SLPushBack(&s, 30);SLPushBack(&s, 40);SLPrint(&s);int* p1 = (int*)malloc(sizeof(int)* 10);assert(p1);printf("p1:%p\n", p1);int* p2 = (int*)realloc(p1, sizeof(int)* 5);assert(p2);printf("p2:%p\n", p2);
}void TestSeqList4()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPushBack(&s, 5);SLPrint(&s);//SLInsert(&s, 2, 30);SLInsert(&s, 0, 30);SLPrint(&s);int x = 0;scanf("%d", &x);int pos = SLFind(&s, x);if (pos != -1){SLInsert(&s, pos, x * 100);}SLPrint(&s);
}void TestSeqList5()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPushBack(&s, 5);SLPrint(&s);SLErase(&s, 0);SLPrint(&s);int x = 0;scanf("%d", &x);int pos = SLFind(&s, x);if (pos != -1){SLErase(&s, pos);}SLPrint(&s);
}void memu()
{printf("****************************************\n");printf("1、尾插数据 2、头插数据\n");printf("7、打印数据 -1、退出\n");printf("****************************************\n");
}int main()
{SL s;SLInit(&s);int option = 0;int x = 0;do{memu();printf("请输入你的操作:>");scanf("%d", &option);switch (option){case 1:printf("请连续输入你要插入的数据,以-1结束\n");scanf("%d", &x);while (x != -1){SLPushBack(&s, x);scanf("%d", &x);}break;case 2:break;case 3:break;case 7:SLPrint(&s);break;default:break;}} while (option != -1);SLDestory(&s);return 0;
}

五、顺序表的缺陷

顺序表存在如下缺陷:

  • 在头部/中间的插入与删除需要挪动数据,时间复杂度为O(N),效率低;
  • 增容需要申请新空间,可能会拷贝数据,释放旧空间,会有不小的消耗;
  • 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到 200,如果我们再继续插入了5个数据,后面没有数据插入了,那么会浪费95个数据空间;

针对顺序表存在的这些缺陷,我们设计出了链表。


六、顺序表力扣OJ题

1、移除元素

题目链接

27. 移除元素 - 力扣(LeetCode)

题目描述

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。image-20220728174857575

思路分析

思路1

循环遍历,挪动覆盖数据:遍历这个数组,每当遇见等于val的元素时,就将数组后面的元素整体向前挪动一位。
在这里插入图片描述

时间复杂度:O(N^2) 空间复杂度:O(1)。

思路2

遍历数组,挪动元素到新空间:开辟一个新的数组,然后遍历原来的数组,将不等于val的元素放入新开辟的数组中,将等于val的元素丢弃;最后让新开辟的数组覆盖掉原数组。
在这里插入图片描述

时间复杂度:O(N) 空间复杂度:O(N) 因为开辟了一个新空间。

思路3

遍历数组,挪动覆盖数据(双指针解法):定义两个指针src 和 dst,最开始都指向数组第一个元素,然后开始遍历数组;如果arr[src] != val,那么让arr[dst] = arr[src],然后 src++,dst++;如果 arr[src]==val,则 src++,dst不动;这样一直往后遍历,知道把数组所有元素都遍历完。
在这里插入图片描述

思路三代码实现

int removeElement(int* nums, int numsSize, int val) {int src=0,dst=0;while(src < numsSize){if(nums[src]==val){++src;}else{nums[dst]=nums[src];++dst;++src;}}return dst;
}

2、删除有序数组中的重复项

题目链接

26. 删除有序数组中的重复项 - 力扣(LeetCode)

题目描述

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。image-20220728200421875

思路分析

这道题的解题思路和上面的移除元素十分相似,都是使用双指针;让 src 和 dst 都指向数组第一个元素,然后判断 arr[src] 和 arr[dst] 是否相等,如果相等,说明是重复元素,则让 src++,dst 不动;如果不相等,就让dst++,然后将 arr[src] 赋给 arr[dst],再让 src++;然后一直往后遍历数组,直到将数组遍历完。

时间复杂度:O(N) 空间复杂度:O(1)

代码实现

int removeDuplicates(int* nums, int numsSize) {int src = 0;int dst = 0;while (src < numsSize) {if (nums[src] != nums[dst]) {nums[++dst] = nums[src++]; // 注意:dst 是前置++} else {src++;}}return dst + 1; // 由于 dst 是前置++,所以返回值需要 +1 (数组下标从0开始)
}

3、合并两个有序数组

题目链接

88. 合并两个有序数组 - 力扣(LeetCode)

题目描述

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。image-20220728201642640

思路分析

思路:开辟新数组,把数据有序的放入数组中(双指针法):因为两个原数组都是有序的,所以我们可以用两个指针 src1 和 src2 分别指向两个数组,如果src1 指向的元素小于 src2,就把src1的数据放入新数组中然后通过比较大小的方式把数据依次放入新数组中,最后新数组的数据覆盖掉原数组的数据。

在这里插入图片描述

思路代码实现

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {int end1 = m - 1; // 指向数组1最后一个有效数据int end2 = n - 1; // 指向数组2末尾int end = m + n - 1; // 指向数组1末尾while (end1 >= 0 && end2 >= 0) { // 当其中一个数组遍历完成后循环结束if (nums1[end1] < nums2[end2]) { // 从后往前,需要找大的nums1[end--] = nums2[end2--];} else {nums1[end--] = nums1[end1--];}}// 如果数组1中还有元素则不用管,因为它本来就是有序的if (end2 >= 0) { // 如果数组2还有元素while (end2 >= 0) {nums1[end--] = nums2[end2--];}}
}

希望给大家带来帮助!!
一起加油! 我要去西电!!!!!

在这里插入图片描述

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

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

相关文章

ThreeJs制作模型图片

这个标题名字可能有歧义&#xff0c;只是不知道如何更好的表达&#xff0c;总之就是将图片的像素转换成3D场景的模型&#xff0c;并设置这个模型的颜色&#xff0c;放到像素点对应的位置从而拼接成一个图片&#xff0c;起因是上文中用js分解了音乐&#xff0c;实现了模型跳动效…

互联网行业的应届大学生,如何制作高水平简历?

雇主通常只会花大约25秒的时间浏览一份简历,因此,拥有一份出色的简历对于找到理想工作至关重要。如果您的简历没有令人印象深刻的特点,那么如何才能在竞争激烈的求职市场中脱颖而出呢? 如果您不知道如何在简历上有效地展示自己,或者觉得简历无论怎么修改都不够突出,那么请…

安装、配置MySQL

安装相关软件 MySQL Server、MySQL Workbench MySQL Server&#xff1a;专门用来提供数据存储和服务的软件 MySQL Workbench&#xff1a;可视化的 MySQL 管理工具 官网安装 https://www.mysql.com/ 官网 MySQL :: Download MySQL Installer 安装包路径 在这里选择版本和和对应…

多图如何导入多个二维码?图片批量导出二维码的技巧

多个图片分别生成对应的二维码怎么做&#xff1f;现在扫码看图片是一种很常用的内容预览方式&#xff0c;有些产品包装也会采用这种方式来展示对应的信息&#xff0c;怎么简单快速的将图片生成二维码&#xff0c;相信有很多的小伙伴都非常的感兴趣。那么小编通过下面这篇文章来…

探索C++中的动态数组:实现自己的Vector容器

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

echarts line绘制机组开关状态折线图

2024.3.12今天我学习了如何用echarts line实现设备开关状态的效果。 代码如下&#xff1a; option {xAxis: {type: time,},yAxis: {type: value,splitNumber:2,// axisLine: {// show: true,// lineStyle: {// color:#808080// }// },axisLabel:{formatt…

管控员工上网行为(让老板管理更省心更高效)

很多老板都有这样一种顾虑&#xff1a; 员工到底有没有认真工作&#xff0c;工作是不是做到了全身心投入。 为什么会有担心员工工作状态的问题发生&#xff1f; 无疑是员工在上班时间浏览与工作无关的网站、下载私人文件、甚至是泄露公司机密等行为&#xff0c;让老板不放心了…

Elasticsearch:在本地使用 Gemma LLM 对私人数据进行问答

在本笔记本中&#xff0c;我们的目标是利用 Google 的 Gemma 模型开发 RAG 系统。 我们将使用 Elastic 的 ELSER 模型生成向量并将其存储在 Elasticsearch 中。 此外&#xff0c;我们将探索语义检索技术&#xff0c;并将最热门的搜索结果作为 Gemma 模型的上下文窗口呈现。 此外…

岭回归:优化预测的利器

在数据科学和机器学习的领域&#xff0c;构建准确、稳定的预测模型是一项至关重要的任务。岭回归作为一种强大的工具&#xff0c;被设计用来应对数据集中存在多重共线性的问题&#xff0c;并通过引入正则化来缩小预测误差。 1. 岭回归的原理&#xff1a; 岭回归是线性回归的一…

【国产】API接口管理平台的产品设计与搭建讲解

【国产接口管理平台】PhalApi Pro (π框架专业版) PhalApi Pro (发音&#xff1a;π框架专业版)&#xff0c;是一款国产企业级API接口管理平台&#xff0c;可以零代码、快速搭建API接口开发平台、接口开放平台、接口管理平台。基于PhalApi开源接口开发框架&#xff0c;通过低代…

【gpt实践】李某的AI课程值199吗

先说个人的答案&#xff1a;不值。但也不是说毫无价值&#xff0c;只是他的价值没那么高。 文末分享该课程&#xff0c;大家有兴趣可以看看&#xff0c;该课程是否有价值。 “清华博士”推出的199元的AI课程销售额竟然突破了5000万。这一数字让人惊叹&#xff0c;也引发了人们…

亚马逊、速卖通卖家如何做好测评让店铺销量稳定增长?

近期有刚入驻跨境电商的新买家咨询珑哥&#xff0c;店铺上的产品有人浏览&#xff0c;就是没有人下单&#xff0c;新店铺很正常因为很多人去购买东西&#xff0c;首先看的是评价&#xff0c;没有评价一般人不敢直接去下单。就像我们去淘宝买东西&#xff0c;都要看下评价&#…

测试用例的设计(2)

目录 1.前言 2.正交排列(正交表) 2.1什么是正交表 2.2正交表的例子 2.3正交表的两个重要性质 3.如何构造一个正交表 3.1下载工具 3.1构造前提 4.场景设计法 5.错误猜测法 1.前言 我们在前面的文章里讲了测试用例的几种设计方法,分别是等价类发,把测试例子划分成不同的类…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)上篇

提供具有网页显示能力的Web组件&#xff0c;ohos.web.webview提供web控制能力。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。示例效果请以真机运行为准&#xff0c;当前IDE预览器不支持。 需要权…

Java项目:基于springboot实现的OA协同办公系统(源码+数据库+毕业论文)

一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…

从零开始利用MATLAB进行FPGA设计(一):建立脉冲检测模型的Simulink模型2

目录 1.模块的总体结构 1.1从工作空间导入输入信号 1.2FIR滤波器 2.Subsystem 3.MATLAB Function 文章灵感来源于MATLAB官方免费教程&#xff1a;HDL Coder Self-Guided Tutorial 考虑到MATLAB官网的英文看着慢&#xff0c;再加上视频讲解老印浓浓的咖喱味&#xff0c;我…

【CSP】2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度(思想是离散化)

2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度&#xff08;思想是离散化&#xff09;2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度&#xff08;思想是离散化&#xff09; 2021-12-2 序列查询新解 分段处理 用乘法代替加法减少时间复杂度&am…

echarts绘制柱状图

<template><div><div>【大区数据信息】</div><div ref"target" class"w-full h-full" ></div></div> </template><script setup> import { ref, onMounted, watch} from "vue"; import *…

RC522刷卡电路设计及程序

一、RC522刷卡电路组成 基于RC522的刷卡电路如上图所示。该电路组成主要分为三部分&#xff1a; Receiving Circuit&#xff1a;接收电路&#xff0c;接收卡发送的数据。 Filtering Impedence-Transtorm circuit:滤波和阻抗变换电路&#xff0c;抑制高次谐波并优化到读卡器天线…

手把手写深度学习(23):视频扩散模型之Video DataLoader

手把手写深度学习(0)&#xff1a;专栏文章导航 前言&#xff1a;训练自己的视频扩散模型的第一步就是准备数据集&#xff0c;而且这个数据集是text-video或者image-video的多模态数据集&#xff0c;这篇博客手把手教读者如何写一个这样扩散模型的的Video DataLoader。 目录 准…