【数据结构】——顺序表

news2024/11/25 20:40:47

目录

1.线性表

 2.顺序表

2.1概念及结构

3.静态顺序表

4.动态顺序表

1.定义一个顺序表

2.顺序表的初始化和销毁

3.顺序表尾插

4.顺序表打印

5.顺序表尾删

6.顺序表头插

7.顺序表头删

8.在pos(任意)位置的插入

9.在pos(任意)位置的删除

5.简单的写一个菜单

6.完整的动态顺序表代码

 6.1SeqList.h

 6.2SeqList.c

 6.3Test.c


1.线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。

线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,

线性表在物理上存储时,通常以数组和链式结构的形式存储。

 2.顺序表

2.1概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存

储。在数组上完成数据的增删查改。

顺序表一般可以分为:

1. 静态顺序表:使用定长数组存储元素。

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

顺序表的本质就是数组

顺序表要求的是连续存储

3.静态顺序表

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定了,空间开多了浪费,开少了不够用。因此现实生活场景基本不会用到静态顺序表

 

接下来用代码看一看静态顺序表是怎么实现的:

// 静态顺序表 -- 不太实用
// N小了不够用,N大了可能浪费
#define N  100
//typedef struct shunxubiao//不能用拼英取名字
typedef int SLDataType;//重命名结构中的数据类型,以便后期维护
typedef struct SeqList
{
	SLDataType a[N];
	int size; // 记录存储多少个有效数据
}SL;

// STL命名风格
//void SeqListInit(SL s);

void SLInit(SL s);
void SLPushBack(SL s, SLDataType x);

//void SLWeicha(SL s, int x);//不能这样取名字

4.动态顺序表

相比于静态顺序表,动态顺序表能够改变内存空间的大小,因此不会出现内存过大或者太小的情况,更适用于平时日常生活的场景。

 接下来用代码看一看动态顺序表是怎么实现的:

1.定义一个顺序表

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;
	int size;       // 记录存储多少个有效数据
	int capacity;   // 空间容量大小 
}SL;

2.顺序表的初始化和销毁

//顺序表初始化
void SLInit(SL* ps)
{
	assert(ps);

	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

//顺序表销毁
void SLDestroy(SL* ps)
{
	assert(ps);

	//if (ps->a != NULL)
	if (ps->a)
	{
		free(ps->a);
		ps->a = NULL;
		ps->size = ps->capacity = 0;
	}
}

3.顺序表尾插

1.先判断数组的容量够不够

2.如果不够的话就需要扩容

3.扩容完成之后,将想要插入的数据x插入到尾部

void SLPushBack(SL* ps, SLDataType x)
{
    //版本1
	assert(ps);

	// 扩容
	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);//终止程序
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}

	ps->a[ps->size] = x;
	ps->size++;

    //版本2
    assert(ps);

	SLCheckCapacity(ps);

	ps->a[ps->size] = x;
	ps->size++;

    //版本3
    SLInsert(ps, ps->size, x);
}

PS:

探究realloc扩容是原地扩容还是异地扩容

 

4.顺序表打印

void SLPrint(SL* ps)
{
	assert(ps);

	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

5.顺序表尾删

PS:并不需要将尾部的那个数据置为0,因为有可能我们存的就是0

我们只需要缩减数组的长度size就行了,缩减一次,就相当于尾部的数据被删除了

那么下次我们尾插的时候,虽然这个数据还在,但是也会被覆盖掉

要注意的是size为0的时候就不能进行尾删了

void SLPopBack(SL* ps)
{
    //版本1
	assert(ps);

	// 温柔的检查
	/*if (ps->size == 0)
	{
	return;
	}*/

	// 暴力的检查
	assert(ps->size > 0);

	//ps->a[ps->size - 1] = 0;
	ps->size--;

    //版本2
    SLErase(ps, ps->size-1);
    
}

6.顺序表头插

在数组的头部插入一个数据

 

 如果空间满了就需要扩容,想到之前尾插的时候也需要扩容,因此可以将这两次扩容写成一个扩容函数

//扩容函数
void SLCheckCapacity(SL* ps)
{
	assert(ps);

	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}
}
void SLPushFront(SL* ps, SLDataType x)
{
	//版本1
	assert(ps);
	//检查扩容
	SLCheckCapacity(ps);

	// 挪动数据
	int end = ps->size - 1;
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}

	ps->a[0] = x;
	ps->size++;

	//版本2
	SLInsert(ps, 0, x);
}

7.顺序表头删

删除头部的一个元素,将后面的元素整体向前挪动一个元素的空间,就能覆盖掉第一个元素

分析图如下:

(版本1的代码)

 代码如下:

void SLPopFront(SL* ps)
{
	//版本1
	assert(ps);
	assert(ps->size > 0);

	int begin = 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}

	ps->size--;
	
    //版本2
	SLErase(ps, 0);
}

PS:越界是不一定报错的,尤其是越界读

      

 越界读只是去查看越界位置处的值,因此大部分编译器不会报错

但是越界写是去改变越界位置处的值,这个是不被允许的,属于非法访问了,因此可能会被查出来,但是根据每个编译器查越界位置的监察位置不同,可能会导致查不出的情况,

8.在pos(任意)位置的插入

 参考代码如下:

// 在pos位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos <= ps->size);

	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}

	ps->a[pos] = x;
	ps->size++;
}

由于上面的代码实现的是任意位置插入,那么头插和尾插也属于任意位置中的两种特殊情况

那么SLInsert()能够被复用,去修改上面提到的尾插和头插的代码。 

9.在pos(任意)位置的删除

 参考代码如下:

// 删除pos位置数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);
	//assert(ps->size > 0);

	// 挪动数据覆盖
	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}

	ps->size--;
}

既然pos(任意)位置的值都能被删除了,那么头删和尾删也只是SLErase函数的两者特殊情况,因此头删和尾删的代码能够被SLErase函数替换

 10.找顺序表中某个值

上面的头删和尾删还有pos位置的删除都是通过下标来删除,但是实际生活中,又不是人人都是程序员,别人可能压根不懂下标的概念,那这个时候,我想删除数字10,应该怎么删除呢?

这个时候我们就要去查找数字10对应的下标了,得到下标之后,就能调用上述的函数去删除10了

参考代码如下:

int SLFind(SL* ps, SLDataType x, int begin)
{
	assert(ps);

	for (int i = begin; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}

	return -1;
}

//找到x了,返回下标
/找不到,返回-1

5.简单的写一个菜单

void menu()
{
	printf("***********************************************\n");
	printf("1、尾插数据 2、尾删数据\n");
	printf("3、头插数据 4、头删数据\n");
	printf("5、打印数据 -1、退出\n");
	printf("***********************************************\n");
}

int main()
{
	SL s;
	SLInit(&s);
	int option = 0;
	int val = 0;
	do
	{
		menu();
		printf("请输入你的操作:>");
		scanf("%d", &option);
		switch (option)
		{
		case 1:
			printf("请依次输入你要尾插的数据,以-1结束");
			scanf("%d", &val);
			while (val != -1)
			{
				SLPushBack(&s, val);
				scanf("%d", &val);
			}
			break;
		case 2:
			SLPopBack(&s);
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			SLPrint(&s);
			break;
		default:
			break;
		}
	} while (option != -1);

	SLDestroy(&s);

	return 0;
}

PS:对于初学数据结构的朋友来说,不建议去写菜单,菜单的本质就是便于非程序员使用者和计算机啊交互的,但是对于程序员来说,简洁的菜单反而不利于我们去发现代码中的BUG,不利于我们去调试代码,因此菜单尽量不要去写,要写的话,也只是整个代码的逻辑框架已经写完了,最后再去写菜单。

6.完整的动态顺序表代码

 6.1SeqList.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>


// 动态顺序表 -- 按需扩空间

typedef int SLDataType;
typedef struct SeqList
{
	SLDataType* a;	// 指向动态开辟的数组
	int size;       // 记录存储多少个有效数据
	int capacity;   // 空间容量大小 
}SL;

//顺序表打印
void SLPrint(SL* ps);
//顺序表初始化
void SLInit(SL* ps);
//顺序表销毁
void SLDestroy(SL* ps);
//顺序表尾插
void SLPushBack(SL* ps, SLDataType x);
//顺序表尾删
void SLPopBack(SL* ps);
//顺序表头插
void SLPushFront(SL* ps, SLDataType x);
//顺序表头删
void SLPopFront(SL* ps);

//中间插入删除
//在pos(任意)位置插入数据,
void SLInsert(SL* ps, int pos, SLDataType x);
//删除pos(任意)位置数据
void SLErase(SL* ps, int pos);

//查找顺序表中x值的位置,返回下标
//int SLFind(SL* ps, SLDataType x);
// begin查找x的起始位置
int SLFind(SL* ps, SLDataType x, int begin);

// B树  红黑树  哈希

 6.2SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"


void SLPrint(SL* ps)
{
	assert(ps);

	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
//扩容函数
void SLCheckCapacity(SL* ps)
{
	assert(ps);

	if (ps->size == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}
}

void SLInit(SL* ps)
{
	assert(ps);

	ps->a = NULL;
	ps->size = 0;
	ps->capacity = 0;
}

void SLDestroy(SL* ps)
{
	assert(ps);

	//if (ps->a != NULL)
	if (ps->a)
	{
		free(ps->a);
		ps->a = NULL;
		ps->size = ps->capacity = 0;
	}
}

//时间复杂度O(1)--尽量用尾插,头差时间复杂度高
void SLPushBack(SL* ps, SLDataType x)
{
	//版本1
	//assert(ps);

	// 扩容
	//if (ps->size == ps->capacity)
	//{
	//	int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
	//	SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
	//	if (tmp == NULL)
	//	{
	//		perror("realloc fail");
	//		exit(-1);//终止程序
	//	}

	//	ps->a = tmp;
	//	ps->capacity = newCapacity;
	//}

	//ps->a[ps->size] = x;
	//ps->size++;

	//版本2
	//assert(ps);

	//SLCheckCapacity(ps);

	//ps->a[ps->size] = x;
	//ps->size++;
	
	//版本3
	SLInsert(ps, ps->size, x);
}

void SLPopBack(SL* ps)
{
	//版本1
	//assert(ps);

	 温柔的检查
	///*if (ps->size == 0)
	//{
	//return;
	//}*/

	 暴力的检查
	//assert(ps->size > 0);

	ps->a[ps->size - 1] = 0;
	//ps->size--;

	//版本2
    SLErase(ps, ps->size - 1);
	

}

//时间复杂度O(N)
void SLPushFront(SL* ps, SLDataType x)
{
	版本1
	//assert(ps);
	检查扩容
	//SLCheckCapacity(ps);

	 挪动数据
	//int end = ps->size - 1;
	//while (end >= 0)
	//{
	//	ps->a[end + 1] = ps->a[end];
	//	end--;
	//}

	//ps->a[0] = x;
	//ps->size++;

	//版本2
	SLInsert(ps, 0, x);
}

void SLPopFront(SL* ps)
{
	版本1
	//assert(ps);
	//assert(ps->size > 0);

	//int begin = 1;
	//while (begin < ps->size)
	//{
	//	ps->a[begin - 1] = ps->a[begin];
	//	begin++;
	//}

	//ps->size--;
	//版本2
	SLErase(ps, 0);
}

// 在pos位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos <= ps->size);

	SLCheckCapacity(ps);
	int end = ps->size - 1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}

	ps->a[pos] = x;
	ps->size++;
}

// 删除pos位置数据
void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0);
	assert(pos < ps->size);
	//assert(ps->size > 0);

	// 挪动数据覆盖
	int begin = pos + 1;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}

	ps->size--;
}

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

int SLFind(SL* ps, SLDataType x, int begin)
{
	assert(ps);

	for (int i = begin; i < ps->size; ++i)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}

	return -1;
}

 6.3Test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"

void TestSeqList1()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPushBack(&sl, 5);
	SLPushBack(&sl, 5);
	SLPushBack(&sl, 5);
	SLPushBack(&sl, 5);


	SLPrint(&sl);

	SLDestroy(&sl);
}

void TestSeqList2()
{
	/*SL* s = NULL;
	SLInit(s);*/

	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(&sl);

	SLPopBack(&sl);
	SLPrint(&sl);

	SLPushBack(&sl, 8);
	SLPrint(&sl);

	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPopBack(&sl);
	//SLPopBack(&sl);

	SLPrint(&sl);

	SLPushBack(&sl, 1);
	//SLPushBack(&sl, 2);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 2);


	SLDestroy(&sl);
}

void TestSeqList3()
{
	SL sl;
	SLInit(&sl);

	SLPushFront(&sl, 1);
	SLPushFront(&sl, 2);
	SLPushFront(&sl, 3);
	SLPushFront(&sl, 4);

	SLPrint(&sl);

	SLPopFront(&sl);
	SLPopFront(&sl);
	SLPopFront(&sl);
	SLPopFront(&sl);
	//SLPopFront(&sl);
	SLPrint(&sl);

	SLPushBack(&sl, 10);
	SLPrint(&sl);

	SLDestroy(&sl);
}

void TestSeqList4()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(&sl);

	SLInsert(&sl, 2, 20);
	SLPrint(&sl);

	SLInsert(&sl, 5, 500);
	SLPrint(&sl);

	SLInsert(&sl, 0, 500);
	SLPrint(&sl);

	SLDestroy(&sl);
}

void TestSeqList5()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPrint(&sl);

	SLErase(&sl, 2);
	SLPrint(&sl);

	SLErase(&sl, 2);
	SLPrint(&sl);

	SLErase(&sl, 0);
	SLPrint(&sl);

	SLDestroy(&sl);
}

void TestSeqList6()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPushBack(&sl, 7);
	SLPushBack(&sl, 5);
	SLPushBack(&sl, 8);
	SLPushBack(&sl, 5);
	SLPrint(&sl);

	/*int pos = SLFind(&sl, 5);
	if (pos != -1)
	{
		SLErase(&sl, pos);
	}
	SLPrint(&sl);*/

	int pos = SLFind(&sl, 4, 0);
	if (pos != -1)
	{
		SLErase(&sl, pos);
	}
	SLPrint(&sl);

	// 删除顺序表所有的5
	pos = SLFind(&sl, 5, 0);
	while (pos != -1)
	{
		SLErase(&sl, pos);

		pos = SLFind(&sl, 5, pos);
	}
	SLPrint(&sl);

	SLDestroy(&sl);
}



void menu()
{
	printf("***********************************************\n");
	printf("1、尾插数据 2、尾删数据\n");
	printf("3、头插数据 4、头删数据\n");
	printf("5、打印数据 -1、退出\n");
	printf("***********************************************\n");
}

int main()
{
    //TestSeqList1()
    //TestSeqList2()
    //TestSeqList3()
    //TestSeqList4()
    //TestSeqList5()
    //TestSeqList6()
	SL s;
	SLInit(&s);
	int option = 0;
	int val = 0;
	do
	{
		menu();
		printf("请输入你的操作:>");
		scanf("%d", &option);
		switch (option)
		{
		case 1:
			printf("请依次输入你要尾插的数据,以-1结束");
			scanf("%d", &val);
			while (val != -1)
			{
				SLPushBack(&s, val);
				scanf("%d", &val);
			}
			break;
		case 2:
			SLPopBack(&s);
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			SLPrint(&s);
			break;
		default:
			break;
		}
	} while (option != -1);

	SLDestroy(&s);

	return 0;
}

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

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

相关文章

[附源码]计算机毕业设计JAVAjsp美容院业务管理系统

[附源码]计算机毕业设计JAVAjsp美容院业务管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM m…

用DIV+CSS技术设计的体育篮球主题 校园体育网页与实现制作(web前端网页制作课作业)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

SpringBoot(二):基础配置文件、yaml语法、多环境开发配置

目录 一、配置文件 1、配置文件格式 2、自动提示功能失灵解决方案 3、SpringBoot配置文件加载顺序 二、yaml 1、yaml介绍 2、yaml语法规则 3、yaml数组数据 4、yaml数据读取 三、多环境开发配置 1、多环境启动配置 2、多环境启动命令格式 3、多环境开发控制 四、…

VS Code常用操作

文章目录常用快捷键修改VS Code底部状态栏颜色VS Code添加Anaconda的Python源常用快捷键 (1) 对于 行 的操作&#xff1a; 重开一行&#xff1a;光标在行尾的话&#xff0c;回车即可&#xff1b;      不在行尾&#xff0c;Ctrl Enter 向下重开一行&#xff1b;    …

手拉手一起学HTML(下)——表格标签和列表标签,表单标签

&#x1f353;个人主页&#xff1a;bit.. &#x1f352;系列专栏&#xff1a;Linux(Ubuntu)入门必看 C语言刷题 数据结构与算法 目录 一.表格标签 1.1表格的主要作用 1.2表格的基本语法 1.3表头单元格标签 1.4表格属性 1.5表格结构标签 1.6合并单元格&#xff08…

prometheus 监控

【00】结构原理微服务中的监控分根据作用领域分为三大类&#xff0c;Logging&#xff0c;Tracing&#xff0c;Metrics。* Logging - 用于记录离散的事件。例如&#xff0c;应用程序的调试信息或错误信息。它是我们诊断问题的依据。比如我们说的ELK就是基于Logging。* Metrics -…

HTTP协议详解

1.HTTP协议介绍 先来给大家介绍以下HTTP&#xff1a; HTTP&#xff08;Hyper Text Transfer Protocol&#xff09;&#xff1a; 全称超文本传输协议&#xff0c;是用于从万维网&#xff08;WWW:World Wide Web &#xff09;服务器传输超文本到本地浏览器的传送协议。HTTP 是一种…

【网络篇】如何搭建自己的DNS服务器

引言 平时练习域名解析&#xff0c;一般直接修改的/etc/hosts文件。对于服务器数量小的情况完全可以&#xff0c;但是如果服务器数量较多&#xff0c;每个都修改比较麻烦。 DNS是作为域名解析。在实际的生产过程中&#xff0c;尤其是对于内网搭建的情况&#xff0c;DNS不可能…

宝塔面板如何设置301重定向,为什么网站要设置重定向?

大家好&#xff0c;我是Q站小编鹏仔&#xff0c;本次给大家带来的教程是宝塔面板如何设置301重定向。 在设置之前&#xff0c;我们需先明白为什么要设置重定向呢&#xff1f; 在购买域名时&#xff0c;域名本身是不带有www的&#xff0c;由于在以前网站方都会增加一个"ww…

C#项目实战|人脸识别考勤

此文主要通过WinForm来制作的一个人脸识别考勤打卡程序&#xff0c;有兴趣的小伙伴可以接入到打卡机上。 一、实现流程1.1、创建项目1.2、设计页面1.3、创建应用1.4、获取Token及参数解析1.5、与人脸数据比对并展示一、实现流程 1.1、创建项目 打开Visual Studio&#xff0c;右…

HTML+CSS静态网页设计:(房地产网站设计与实现6页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

javascript事件处理二 事件对象event详解及target和currentTarget区别

在处理事件的时候&#xff0c;所有和事件相关的东西都封装到event这个对象里面。所以这个对象非常的重要。这个对象有非常多的内容&#xff0c;我们讨论几个计较常见和以及比较难区别的target和currentTarget。 常见属性 页面就是一个div&#xff0c;然后我们监听他的oclick事…

Python+大数据-Spark技术栈(三) SparkCore加强

Python大数据-Spark技术栈(三) SparkCore加强 重点&#xff1a;RDD的持久化和Checkpoint提高拓展知识&#xff1a;Spark内核调度全流程&#xff0c;Spark的Shuffle练习&#xff1a;热力图统计及电商基础指标统计combineByKey作为面试部分重点&#xff0c;可以作为扩展知识点 …

NLP | XLNet :用于语言理解的广义自回归预训练 论文详解

论文&#xff1a;XLNet: Generalized Autoregressive Pretraining for Language Understanding 论文地址&#xff1a;https://proceedings.neurips.cc/paper/2019/file/dc6a7e655d7e5840e66733e9ee67cc69-Paper.pdf 1.介绍 XLNet 是从蓬勃发展的自然语言处理 (NLP) 领域中出…

食用前须知(阅读并同意后在食用其他部分)

昨天刚和计科某数据结构老师聊这个事 让我别写题解了 以后会偷摸的在csdn更&#xff0c;大家千万低调点&#xff0c;严谨点&#xff01;&#xff01;&#xff01; 一般不会当天更了&#xff0c;会拖个一两天&#xff0c;大家先把会的写写&#xff0c;不会的再来看我教程 就算真…

高效率Paper写作需要哪些建议?

高效写Paper最关键的是要多写&#xff0c;写多了&#xff0c;英语行文能力提高&#xff0c;并且知道Paper写作大概的套路&#xff0c;Paper写作效率自然上升。小编为同学们带来一些建议。 The key to writing paper efficiently is to write more.If you write more,improve yo…

ijkplayer项目

ijkplayer项目 环境配置 NDK全称&#xff1a;Native Development Kit。 1、NDK是一系列工具的集合。NDK提供了一系列的工具&#xff0c;帮助开发者快速开发C&#xff08;或C&#xff09;的动态库&#xff0c;并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨…

C++ Reference: Standard C++ Library reference: C Library: cwchar: wmemset

C官网参考链接&#xff1a;https://cplusplus.com/reference/cwchar/wmemset/ 函数 <cwchar> wmemset wchar_t* wmemset (wchar_t* ptr, wchar_t wc, size_t num); 填充宽字符数组 将由ptr指向的宽字符数组的第一个num个元素设置为wc指定的值。 这是memset&#xff08;&…

瑞吉外卖强化(一):缓存优化

瑞吉外卖强化&#xff08;一&#xff09;&#xff1a;缓存优化瑞吉外卖 缓存优化Redis基本操作短信验证码 缓存实现缓存菜品数据SpringCache常用注解瑞吉外卖 缓存优化 Redis基本操作 redisTemplate需要配置类 这里的 需要对其进行 序列化操作 reidsTeplate.opsForValue().s…

HummerRisk 快速入门教程

1、一键部署 1. 部署服务器要求 操作系统要求&#xff1a;任何支持 Docker 的 Linux x64CPU内存要求&#xff1a;最低要求 4C8G&#xff0c;推荐 8C16G部署目录空间&#xff08;默认/opt目录&#xff09;要求&#xff1a; 50G网络要求&#xff1a;可访问互联网&#xff08;如…