【数据结构——顺序表】线性表很难嘛?这篇文章能让你轻松掌握顺序表

news2024/11/16 13:53:38

线性表

线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…。线性表在逻辑上是线性结构,也就是说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式的结构的形式存储。

线性表的概念:

  • 是n个具有相同元素特性的数据元素的有限序列。
  • 有穷性:一个线性表中的元素是有限的。
  • 一致性:一个线性表中所有的元素的性质相同。
  • 有序性:一个线性表中所有的元素之间的相对位置是线性的,即存在唯一的开始元素和终端元素,除此之外,每个元素都只有唯一的前驱元素和后继元素。各元素在线性表中的位置只取决于它们的序号,所以一个线性表中可以存在两个及以上的相同元素。

线性表的作用:

线性表一般用于存储有顺序关系的数列。最典型的例子就是为队列(先进先出)、栈(先进后出)。

线性表支持的操作:

  • **插入元素:**在线性表的指定位置插入一个元素,(insert、pushBack、pushFront等函数)。
  • **删除元素:**在线性表的指定位置删除一个元素,(pop、、popBack、popFront等函数)。
  • **访问元素:**访问线性表中指定位置的一个元素,(下标操作符[]等)。

线性表的逻辑结构图

image.png
image.png

顺序表

顺序表的概念:

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

顺序表的结构:

静态结构:使用定长数组存储

//静态顺序表
#define n 10

typedef int SLDataType;
typedef struct SeqList
{
	//定长数组
	SLDataType arr[n];
	//有效数据的个数
	int size;
}SeqList;

静态顺序表最大的缺陷就是,当数据存放满的时候就需要手动去增加,如果程序写成这样那会被骂死的,所以顺序有引入了动态顺序表。

动态结构:使用动态开辟的数组存储

//动态顺序表
typedef int SLDataType;

typedef struct SeqList
{
	//指向动态开辟的数组
	SLDataType* arr;
	//有效数据的个数
	int size;
	//容量空间的大小
	int capacity;
}SeqList;

当数组的空间满了,程序就会自动的扩容,这样相较与静态顺序表来说就灵活了很多,但是还是会造成空间浪费,后面我会讲一个更好的结构。

接口实现:

下面我们来用动态顺序表来实现对数据的增删查改。因为静态顺序表实用性不怎么强我这里就不演示了,直接开干动态顺序表:

首先就是初始化顺序表:

//顺序表的初始化
void SeqListInit(SeqList* ps)
{
	//断言传过来的指针是否为空
	assert(ps);
	//首先把指向数组的指针置空
	ps->arr = NULL;
	//在把有效数据个数置空
	ps->size = 0;
	//给容量付个初始值
	ps->capacity = 0;
}

对空间进行扩容:

// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* ps)
{
	//对指针进行断言
	assert(ps);
	//判断空间是否为空或者数据满了
	if (ps->size==ps->capacity)
	{
		//定义一个变量来接收容量的值
		//当容量的值为0的时候直接赋值为4,不为空的时候直接*2
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//创建一个指针来接收开辟的空间的地址
		SLDataType* pf = NULL;
		//使用realloc来开辟空间
		pf = (SLDataType*)realloc(ps->arr, newcapacity*sizeof(SLDataType));
		//检查是否开辟成功
		if (pf==NULL)
		{
			perror("realloc");
			//退出程序
			exit(-1);
		}
		//把开辟的空间的地址赋值个arr指针
		ps->arr = pf;
		//同时把新空间容量的大小赋值给结构中用来记录容量的值
		ps->capacity =newcapacity;
	}
}

打印顺序表:

// 顺序表打印
void SeqListPrint(SeqList* ps)
{
	//断言
	assert(ps);
	//通过循环打印
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//换行
	printf("\n");
}

顺序表销毁:

// 顺序表销毁
void SeqListDestory(SeqList* ps)
{
	//断言
	assert(ps);
	//释放空间
	free(ps->arr);
	//然后把指针置空
	ps->arr = NULL;
	//把有效数据个数和容量空间的大小都置为0
	ps->capacity = 0;
	ps->size = 0;
}

顺序表尾插:

在尾插的时候要考虑两种情况:

  1. 当顺序表为空或者顺序表满的时候(调用空间扩容的接口)
  2. 正常的尾插
// 顺序表尾插
void SeqListPushBack(SeqList* ps, SLDataType x)
{
	//断言
	assert(ps);
	//对空间进行扩容
	CheckCapacity(ps);
	//把要插入的值插入顺序表
	ps->arr[ps->size] = x;
	//把记录有效数据个数的变量加1
	ps->size++;
	
}

在主函数中的代码:

#include"List.h"

void List1()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2); 
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}

int main()
{	
	List1();
	return 0;
}

以下是测试结果:
image.png

顺序表尾删:

  • 只有顺序表中有数据的时候才能删除
  • 只有最后一个数据的时候就不删除了
// 顺序表尾删
void SeqListPopBack(SeqList* ps)
{
	//断言指针是否为空
	assert(ps);
	//当只有size大于0的时候才能尾删
	assert(ps->size > 0);
	//尾删
	ps->size--;
}

测试运行结果:
测试的代码

void List1()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2); 
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}

运行结果:
image.png
这就是断言起到的作用,当删除的数据太多的时候就会中止程序。
下面是正常删除的演示
测试代码:

void List1()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2); 
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	
	SeqListDestory(&sl);
}

运行结果:
image.png

顺序表头插:

  1. 首先对顺序表进行扩容
  2. 把数据向后移动空出头的位置
  3. 把数据插入进去同时有效数据个数要加1

代码如下:

// 顺序表头插
void SeqListPushFront(SeqList* ps, SLDataType x)
{
	//断言指针是否为空
	assert(ps);
	//扩容
	CheckCapacity(ps);
	//定义一个变量来接收顺序表中的有效个数
	int i = ps->size;
	//把数据向后移动空出头的位置
	while (i)
	{
		ps->arr[i] = ps->arr[i- 1];
		i--;
	}
	//给头的位置赋值
	ps->arr[0] = x;
	//然后有效数据个数加1
	ps->size++;
}

测试代码和运行结果:
测试代码:

void List2()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListPushFront(&sl, 0);
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}

运行结果:
image.png

顺序表头删:

  1. 控制顺序表中的数据个数大于0
  2. 把后面的数据向前移动

接口代码如下:

//顺序表头删
void  SeqListPopFront(SeqList* ps)
{
	//断言
	assert(ps);
	//控制size的值大于0
	assert(ps->size > 0);
	//定义一个变量来接收顺序表中的有效个数
	int i = 1;
	//把后面的数据向前移动
	while (i<ps->size)
	{
		ps->arr[i - 1] = ps->arr[i];
		i++;
	}
	//把有效数据减1
	ps->size--;
}

测试代码和运行结果:
测试代码:

void List3()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListPopFront(&sl);
	SeqListPrint(&sl);
	SeqListPopFront(&sl);
	SeqListPrint(&sl);	
	SeqListDestory(&sl);
}

运行结果:
image.png

顺序表查找:

  1. 遍历所有的数据
  2. 找到相同的数据
  3. 返回下标
int SeqListFind(SeqList* ps, SLDataType x)
{
	//断言
	assert(ps);
	//遍历数据
	for (int i = 0; i < ps->size; i++)
	{
		//找到数据
		if (ps->arr[i]==x)
		{
			//返回下标
			return i;
		}
	}
	//没有找到返回-1
	return -1;
}

顺序表在pos位置插入x:

  1. 扩容
  2. 把pos位置之后的位置向后移动
  3. 然后再pos位置把数据插入顺序表中
  4. 有效数据个数加1
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDataType x)
{
	assert(ps);
	//扩容
	CheckCapacity(ps);
	assert(0 <= pos && pos <= ps->size);
	int begin = ps->size;
	//把pos之后的数据向后移动
	while (begin>pos)
	{
		
		ps->arr[begin] = ps->arr[begin-1];
		begin--;
	}
	ps->arr[pos] = x;
	ps->size++;

}

测试代码和运行结果:
测试代码:

void List4()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	printf("请输入插入的位置和数据:");
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int pos = SeqListFind(&sl, a);
	if (pos!=-1)
	{
		SeqListInsert(&sl, pos, b);
	}
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}

运行结果:
image.png

顺序表在pos位置删除:

  1. 控制顺序表中的数据个数
  2. 把pos位置之后的数据向前移动
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos)
{
	//断言
	assert(ps);

	//控制数据个数
	assert(ps->size > 0);
	assert(0 <= pos && ps->size > pos);
	int begin = pos;
	//把pos之后的数据向前移动
	while (begin<ps->size)
	{
		ps->arr[begin] = ps->arr[begin + 1];
		begin++;
	}
	ps->size--;
}

测试代码和运行结果:
测试代码:

void List5()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	printf("请输入删除的数据:");
	int a = 0;
	scanf("%d", &a);
	int pos = SeqListFind(&sl, a);
	if (pos != -1)
	{
		SeqListErase(&sl, pos);
	}
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}

运行结果:
image.png

完整代码:

List.c文件代码:

#define _CRT_SECURE_NO_WARNINGS 1

#include"List.h"
//顺序表的初始化
void SeqListInit(SeqList* ps)
{
	//断言传过来的指针是否为空
	assert(ps);
	//首先把指向数组的指针置空
	ps->arr = NULL;
	//在把有效数据个数置空
	ps->size = 0;
	//给容量付个初始值
	ps->capacity = 0;
}

// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* ps)
{
	//对指针进行断言
	assert(ps);
	//判断空间是否为空或者数据满了
	if (ps->size==ps->capacity)
	{
		//定义一个变量来接收容量的值
		//当容量的值为0的时候直接赋值为4,不为空的时候直接*2
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//创建一个指针来接收开辟的空间的地址
		SLDataType* pf = NULL;
		//使用realloc来开辟空间
		pf = (SLDataType*)realloc(ps->arr, newcapacity*sizeof(SLDataType));
		//检查是否开辟成功
		if (pf==NULL)
		{
			perror("realloc");
			//退出程序
			exit(-1);
		}
		//把开辟的空间的地址赋值个arr指针
		ps->arr = pf;
		//同时把新空间容量的大小赋值给结构中用来记录容量的值
		ps->capacity =newcapacity;
	}
}

// 顺序表打印
void SeqListPrint(SeqList* ps)
{
	//断言
	assert(ps);
	//通过循环打印
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//换行
	printf("\n");
}

// 顺序表销毁
void SeqListDestory(SeqList* ps)
{
	//断言
	assert(ps);
	//释放空间
	free(ps->arr);
	//然后把指针置空
	ps->arr = NULL;
	//把有效数据个数和容量空间的大小都置为0
	ps->capacity = 0;
	ps->size = 0;
}

// 顺序表尾插
void SeqListPushBack(SeqList* ps, SLDataType x)
{
	//断言
	assert(ps);
	//对空间进行扩容
	CheckCapacity(ps);
	//把要插入的值插入顺序表
	ps->arr[ps->size] = x;
	//把记录有效数据个数的变量加1
	ps->size++;
	
}

// 顺序表尾删
void SeqListPopBack(SeqList* ps)
{
	//断言指针是否为空
	assert(ps);
	//当只有size大于0的时候才能尾删
	assert(ps->size > 0);
	//尾删
	ps->size--;
}

// 顺序表头插
void SeqListPushFront(SeqList* ps, SLDataType x)
{
	//断言指针是否为空
	assert(ps);
	//扩容
	CheckCapacity(ps);
	//定义一个变量来接收顺序表中的有效个数
	int i = ps->size;
	//把数据向后移动空出头的位置
	while (i)
	{
		ps->arr[i] = ps->arr[i- 1];
		i--;
	}
	//给头的位置赋值
	ps->arr[0] = x;
	//然后有效数据个数加1
	ps->size++;
}

//顺序表头删
void  SeqListPopFront(SeqList* ps)
{
	//断言
	assert(ps);
	//控制size的值大于0
	assert(ps->size > 0);
	//定义一个变量来接收顺序表中的有效个数
	int i = 1;
	//把后面的数据向前移动
	while (i<ps->size)
	{
		ps->arr[i - 1] = ps->arr[i];
		i++;
	}
	//把有效数据减1
	ps->size--;
}

// 顺序表查找
int SeqListFind(SeqList* ps, SLDataType x)
{
	//断言
	assert(ps);
	//遍历数据
	for (int i = 0; i < ps->size; i++)
	{
		//找到数据
		if (ps->arr[i]==x)
		{
			//返回下标
			return i;
		}
	}
	//没有找到返回-1
	return -1;
}

// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDataType x)
{
	assert(ps);
	//扩容
	CheckCapacity(ps);
	assert(0 <= pos && pos <= ps->size);
	int begin = ps->size;
	//把pos之后的数据向后移动
	while (begin>pos)
	{
		
		ps->arr[begin] = ps->arr[begin-1];
		begin--;
	}
	ps->arr[pos] = x;
	ps->size++;

}

// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos)
{
	//断言
	assert(ps);

	//控制数据个数
	assert(ps->size > 0);
	assert(0 <= pos && ps->size > pos);
	int begin = pos;
	//把pos之后的数据向前移动
	while (begin<ps->size)
	{
		ps->arr[begin] = ps->arr[begin + 1];
		begin++;
	}
	ps->size--;
}

List.h代码:

#pragma once

#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

//静态顺序表
//#define n 10
//
//typedef int SLDataType;
//typedef struct SeqList
//{
//	//定长数组
//	SLDataType arr[n];
//	//有效数据的个数
//	int size;
//}SeqList;


//动态顺序表
typedef int SLDataType;

typedef struct SeqList
{
	//指向动态开辟的数组
	SLDataType* arr;
	//有效数据的个数
	int size;
	//容量空间的大小
	int capacity; 
}SeqList;

//顺序表的初始化
void SeqListInit(SeqList* ps);
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* ps);
// 顺序表打印
void SeqListPrint(SeqList* ps);
// 顺序表销毁
void SeqListDestory(SeqList* ps);
// 顺序表尾插
void SeqListPushBack(SeqList* ps, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SeqList* ps);
// 顺序表头插
void SeqListPushFront(SeqList* ps, SLDataType x);
//顺序表头删
void  SeqListPopFront(SeqList* ps);
// 顺序表查找
int SeqListFind(SeqList* ps, SLDataType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);


test.c文件代码:

#define _CRT_SECURE_NO_WARNINGS 1

#include"List.h"

void List1()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2); 
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);
	SeqListPopBack(&sl);
	SeqListPrint(&sl);

	SeqListDestory(&sl);
}

void List2()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListPushFront(&sl, 0);
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}

void List3()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	SeqListPopFront(&sl);
	SeqListPrint(&sl);
	SeqListPopFront(&sl);
	SeqListPrint(&sl);	
	SeqListDestory(&sl);
}

void List4()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	printf("请输入插入的位置和数据:");
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int pos = SeqListFind(&sl, a);
	if (pos!=-1)
	{
		SeqListInsert(&sl, pos, b);
	}
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}
void List5()
{
	SeqList sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl, 1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);
	SeqListPushBack(&sl, 5);
	SeqListPrint(&sl);
	printf("请输入删除的数据:");
	int a = 0;
	scanf("%d", &a);
	int pos = SeqListFind(&sl, a);
	if (pos != -1)
	{
		SeqListErase(&sl, pos);
	}
	SeqListPrint(&sl);
	SeqListDestory(&sl);
}
int main()
{	
	List5();
	return 0;
}

力扣真题

移除元素:

题目如下:移除元素
image.png
解题思路:

  1. 首先定义两个变量(用来当作下标)赋初始值为0;
  2. 然后要是不等于val
  3. 那么就把赋值给另一个下标的空间
  4. 否则就是直接把下标加1
  5. 返回的是另一个下标

代码如下:

int removeElement(int* nums, int numsSize, int val){
    //定义两个变量
    int src=0;
    int dest=0;
    //控制src的值不能越界
    while(src<numsSize)
    {
        //要是不等于就直接赋值
        if(nums[src]!=val)
        {
            nums[dest]=nums[src];
            dest++;
            src++;
        }
        else
        {
            src++;
        }
    }
    return dest;
}

题目如下:
删除有序数组中的重复项
image.png
解题思路:
image.png

  1. 首先创建两个变量来充当下标
  2. 然后把其中一个下标的初始值赋值为1,另一个为0
  3. 当两个下标指向的值不相等的时候就先把为0的下标加1,然后再把初始值为1的下标的值赋值个另一个下标
  4. 反之直接就第一个下标加1
  5. 返回的是第一个下标加1

代码如下:

int removeDuplicates(int* nums, int numsSize){
    int n=numsSize;
    int dst=0;
    int src=1;
    while(src<n)
    {
        if(nums[dst]!=nums[src])
        {
            nums[dst+1]=nums[src];
            dst++;
            src++;
        }
        else
        {
            src++;
        }
    }
    return dst+1;

}

以上就是我关于线性表中的顺序表的总结主要从顺序表的结构、顺序表的接口实现和力扣真题这3个方面进行总结,在线性表中不止有顺序表还有链表,下篇主要就是围绕顺序表来总结,希望这篇博客对大家有用。

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

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

相关文章

创建一个简单的外卖订餐系统

在今天的快节奏生活中&#xff0c;外卖订餐系统已经成为了人们日常生活中不可或缺的一部分。这些系统通过在线点餐和配送服务&#xff0c;为用户提供了便捷的用餐体验。在本文中&#xff0c;我们将创建一个简单的外卖订餐系统&#xff0c;使用Python和Flask框架构建后端&#x…

浅析安防监控系统/AI视频智能分析算法:河道水文水位超标算法应用

传统的水位水尺刻度尺位监测中&#xff0c;所采用的人工读数方式&#xff0c;效率较为低下且 人工成本较高&#xff0c;不利于作业流程的数字化。尽管感应器检测会自动对水位的模拟输入进行筛选&#xff0c;但是由于成本、使用场景要求高、后续日常维护复杂等多种因素&#xff…

电脑文件找回怎么做?文件恢复,就用这3招!

“着急&#xff01;大家伙有什么比较简单的电脑文件找回方法吗&#xff1f;我对电脑不太熟悉&#xff0c;在操作的时候有些文件不知道是被删除了还是丢失了&#xff0c;现在非常需要找回这些丢失的文件&#xff01;” 其实&#xff0c;在使用电脑的过程中&#xff0c;很多电脑用…

学Python的漫画漫步进阶 -- 第十二步

学Python的漫画漫步进阶 -- 第十二步 十二、文件读写12.1 打开文件12.2 关闭文件12.2.1 在finally代码块中关闭文件12.2.2 在with as代码块中关闭文件 12.3 读写文本文件12.4 动动手——复制文本文件12.5 读写二进制文件12.6 动动手——复制二进制文件12.7 练一练12.8 文件读写…

万物目标识别——Detic使用图像级别的监督信号来进行目标检测模型推理(C++/Python)

一、目标识别 1.1 传统目标识别算法 传统目标检测通常将分类&#xff08;确定物体属于哪个类别&#xff09;和定位&#xff08;确定物体的位置&#xff0c;通常使用边界框bbox表示&#xff09;任务耦合在一起。这要求训练数据集中包含每个物体的类别标签以及其对应的bbox位置…

【Proteus仿真】【STM32单片机】智能手环

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 系统运行后&#xff0c;OLED显示温度、心率、加速度极其阈值&#xff1b; 可按下K3键进入阈值设置模式&#xff0c;K1和K2调节对应阈值&#xff0c;K4确定&#xff1b;当检测体温、心率、加速度超出阈值范…

通讯协议介绍CoAP 协议解析

目录 1 通讯协议 2 TCP/IP 网络模型 2.1 TCP协议 2.1.1 TCP 连接过程 2.1.2 TCP 断开连接 2.1.3 TCP协议特点 2.2 UDP协议 2.2.1 UDP 协议特点 3 应用层协议简介 3.1 HTTP 协议 3.2 CoAP 协议 3.3 MQTT 协议 4 CoAP 协议详解 4.1 REST 风格 4.2 CoAP 首部分析 4…

网店怎么进行有效推广?可以试试软文推广

商家在为自己的网店制定推广方案时&#xff0c;不管是从渠道、手段、客户群体哪个方面出发都会面临挑战。传统推广方式成本过高&#xff0c;而宣传效果不一定明显&#xff0c;我们可以试试利用软文推广&#xff0c;成本较低而且推广效果明显。接下来媒介盒子就告诉大家&#xf…

四川玖璨电子商务有限公司:短视频运营理解

短视频运营是一种通过策划、执行和管理短视频内容以达到品牌目标的一项工作。在如今面临信息爆炸的时代&#xff0c;短视频已经成为了吸引用户注意力的一种重要方式。作为一种新兴媒体形式&#xff0c;短视频拥有跨时空、生动有趣、内容丰富的特点&#xff0c;因此得到了越来越…

智能遥测终端机RTU的好处介绍

智能遥测终端机RTU是一种具有高度智能化复合功能的遥测装置&#xff0c;它通过数据采集、通信传输和自动控制等技术&#xff0c;实现对被监测系统的远程监控、数据分析、故障诊断和远程控制。它在工业自动化领域的广泛应用&#xff0c;给自动化程度的提高、成本的下降和生产效率…

Linux 内存泄漏检测的基本原理

一、mtrace分析内存泄露 mtrace&#xff08;memory trace&#xff09;&#xff0c;是 GNU Glibc 自带的内存问题检测工具&#xff0c;它可以用来协助定位内存泄露问题。 它的实现源码在glibc源码的malloc目录下&#xff0c;其基本设计原理为设计一个函数 void mtrace ()&…

开学季ipad手写笔哪款好?平价电容笔牌子排行

随着新学期的临近&#xff0c;随着Apple Pencil的火爆&#xff0c;出现了很多新款的平板电脑的电容笔&#xff0c;也开始在国内上市&#xff0c;有些是品质很高&#xff0c;有些是价位很实惠&#xff0c;而且大部分人都能接受。但是&#xff0c;也存在不少性价比很低的产品。本…

uniapp-video自定义视频封面

uniapp官方文档&#xff1a;video | uni-app官网uni-app,uniCloud,serverlesshttps://uniapp.dcloud.net.cn/uni-app-x/component/video.html#video 主要使用到的是poster属性&#xff0c;详细属性可点击上方api进行查看 <video id"myVideo" class"xwlogo&q…

Go基础语法:概述

概述 1 背景 产生原因 Go是Google开发的一种静态、强类型、编译型、并发型&#xff0c;并具有垃圾回收功能的类C编程语言。2009以开源项目的形式发布&#xff0c;2012年发布1.0稳定版本&#xff0c;距今已经十年了。 Go语言之父Pike提到&#xff1a;Go语言是以C为原型&…

Kubernetes源码阅读环境搭建

参考博文&#xff1a;Kubernetes 源码剖析-环境准备 安装Go语言 wget https://studygolang.com/dl/golang/go1.14.10.linux-amd64.tar.gz下载源代码 mkdir /goinstall创建一个存放go语言的编译器等组件存放的目录。 tar -zxf go1.14.10.linux-amd64.tar.gz -C /goinstall…

Vulhub靶场环境搭建

在Ubantu系统上搭建靶场环境 一、ubantu系统准备 1.更新安装列表 sudo apt-get update 2.安装docker.io sudo apt install docker.io 查看是否安装成功 docker -v 3.安装pip 检查pip是否安装 pip -V 安装pip apt install python3-pip 或者 apt install pip 再次检查pip…

Arcgis提取点数据经纬度

Arcgis提取点数据经纬度 现已打开tiff影像和采样点的shape文件。目标是提取采样点的经纬度信息然后导出。 打开数据管理工具-要素-添加XY坐标 在点的图层上右击打开属性表时&#xff0c;经纬度信息已经添加到属性表中。 在属性表的左上角中点击导出&#xff0c;导出为文本文…

SpringMVC之自定义注解

目录 一.什么是Java注解 1.简介 2.注解的分类 3.JDK元注解 二.自定义注解 1.自定义注解的分类 1.1.标记Annotation: 1.2.元数据Annotation: 2.如何使用自定义注解 3.案例演示 3.1 获取类、方法及属性上的注解值 3.2Inherited 的使用 3.3获取类属性上的注解属性值 3.…

模电课设:用Multisim设计和分析差分放大电路

1 课设内容 1&#xff09;设计一个差分放大器电路&#xff1b; 2&#xff09;用电流源替换发射极电阻&#xff0c;看看会发生什么&#xff1f; 3&#xff09;差分放大器电路特性之差模传输特性。 2 模型搭建 1&#xff09;设计一个差分放大器电路。 差分放大器电路是由对称…

day4_C++

day4_C 思维导图重载 思维导图 重载 #include <iostream> #include <cstring> using namespace std;class MyString { private:char *str;int size; public:MyString():size(10){str new char[size];strcpy(str,"");}MyString(const char *s){size st…