顺序表和链表

news2024/9/20 0:53:47

顺序表和链表

  • 1.线性表
  • 2.顺序表
    • 2.1 概念和结构
    • 2.2 接口实现
    • 2.3 顺序表的问题及思考
  • 3.链表
    • 3.1 链表的概念和结构
    • 3.2 链表的分类
    • 3.3 链表的实现
    • 3.4 双向链表的实现
  • 4. 顺序表和链表的区别和联系

1.线性表

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构

线性表在逻辑上是线性结构,连续的一条线。
物理结构上并不一定是连续的。
线性表在物理上存储时,一般以数组和链式结构的形式存储

常见线性表:顺序表,链表

顺序表
在这里插入图片描述

无头链表

在这里插入图片描述

2.顺序表

2.1 概念和结构

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

顺序表分为两种:静态顺序表动态顺序表

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

数组长度不能进行改变
在这里插入图片描述

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

数组空间不够,可以进行扩容
默认扩容2倍,扩容一次扩多,浪费;扩少,频繁扩容,影响效率
在这里插入图片描述

2.2 接口实现

接口就是规定要程序做什么,但不在其中实现

动态顺序表的实现

定义数据类型和结构体

typedef int LSdatatype;
typedef struct List
{
	LSdatatype* a;
	int count;
	int capacity;
}LS;

初始化顺序表

必须通过指针才能改变结构体的内容,所有接口都需要传址,而不是传值

//初始化顺序表
void LSinit(LS* ps);


void LSinit(LS* ps)
{
    //需要进行判断,如果是空指针直接结束程序
	assert(ps);
	ps->a = NULL;
	ps->count = 0;
	ps->capacity = 0;
}

在这里插入图片描述

尾插

在进行尾插时,需要考虑内存是否充足,否则就会出现问题。由于在整个程序中,还有其他功能需要判断内存是否充足,所有便将其独立为函数。

void Checkcapacity(LS* ps)
{
	//检查容量
	if (ps->count == ps->capacity)
	{
		int newcapacity = ps->capacity;
		newcapacity == 0 ? 4 : 2 * ps->capacity;
		
		//为了避免内存开辟失败而将指针置为空,便创建临时变量tmp
		LSdatatype* tmp = (LSdatatype*)realloc(ps->a, newcapacity * sizeof(int));
		
		if (tmp == NULL)
		{
			perror("realloc");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

对于realloc函数一般的理解是扩容,但这里就直接拿来开辟内存,是否由问题呢

答案是:没有问题

再一次地仔细地观察realloc函数的定义

在这里插入图片描述

如果返回值为空指针,则 realloc函数与 malloc函数类似

所有以后如果遇到类似的情况也不妨使用 realloc函数,更加的高效。

//尾插
void LSpushback(LS* ps, LSdatatype x);


void LSpushback(LS* ps, LSdatatype x)
{
	assert(ps);
	//判断容量
	Checkcapacity(ps);
	ps->a[ps->count] = x;
	ps->count++;
}

在这里插入图片描述

头插

//头插
void LSpushfront(LS* ps, LSdatatype x);


void LSpushfront(LS* ps, LSdatatype x)
{
	assert(ps);
	//检查容量
	Checkcapacity(ps);
	int end = ps->count - 1;

	//挪动数据,从后往前挪
	while (end >= 0)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[0] = x;
	ps->count++;
}

在这里插入图片描述

尾删

//尾删 --最简单直接将指针ps->a向前移动
void LSpopback(LS* ps);
void LSpopback(LS* ps, LSdatatype x)
{
	assert(ps);

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

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

如果数据都已经被删完,还继续删除数据的话,便会使内存崩溃,所有需要进行检查,有两个检查方式:温柔和暴力。

在这里插入图片描述

查找顺序表中的数据

//查找顺序表中的数据   找不到返回-1
int LSfind(LS* ps, LSdatatype* x);


int LSfind(LS* ps, LSdatatype* x)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->count; i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

插入指定数据

//插入指定数据
void LSinsert(LS* ps, size_t pos, LSdatatype* x);

void LSinsert(LS* ps, size_t pos, LSdatatype* x)
{
	assert(ps);
	//相等时表示尾插
	assert(pos<=ps->count)
	
	Checkcapacity(ps);
	size_t end = ps->count;
	while (pos < end)
	{
		ps->a[end] = ps->a[end-1];
		end--;
	}
	ps->a[pos] = x;
	ps->count++;
}

由于posend的类型不同,循环条件的不同,可能会造成程序死循环
循环条件为 pos <= end
在这里插入图片描述

这里虽然end 的 数值是负数,但在与pos 进行比较时,会转化为无符号整形,一个相当大的数值,程序便会进入死循环。

在这里插入图片描述

删除数据

//删除数据
void LSerase(LS* ps, size_t pos);

void LSerase(LS* ps, size_t pos)
{
	assert(ps);
	assert(pos < ps->count - 1);
	size_t begin = pos;
	while (begin < ps->count - 1)
	{
		ps->a[begin] = ps->a[begin + 1];
		begin++;
	}
	ps->count--;
}

在这里插入图片描述

//修改数据
void LSmodify(LS* ps, size_t pos, LSdatatype* x);

void LSmodify(LS* ps, size_t pos, LSdatatype* x)
{
	assert(ps);
	assert(pos < ps->count);
	ps->a[pos] = x;
}
//销毁顺序表
//既然申请空间,在程序结束时便需要销毁空间

void LSdestory(LS* ps);

void LSdestory(LS* ps)
{
	assert(ps);
    free(ps->a);
	ps->a = NULL;
	ps->capacity = 0;
	ps->count = 0;
}

2.3 顺序表的问题及思考

  1. 头部,中间的数据插入或删除,需要挪动数据,时间复杂度为O(N)
  2. 增容需要开辟空间,有可能是原地增容,也有可能是异地增容。如果是异地增容需要拷贝数据,释放旧空间,消耗时间
  3. 即使是2倍扩容,也会存在一定的空间浪费

解决以上问题,就需要引出下面的链表

3.链表

3.1 链表的概念和结构

概念:链表是一种物理连续存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的

逻辑结构
在这里插入图片描述
物理结构
在这里插入图片描述

  1. 链式结构在逻辑上是连续的,在物理上却不是
  2. 结点一般是从堆上申请的
  3. 从堆上申请的空间可能会连续

3.2 链表的分类

实际中链表的分类的有很多,这里只介绍两类:单向不带头双向带头

单向不带头:结构简单,一般不会单独用来存储数据。更多的是作为其他数据结构的子结构,例如哈希桶
在这里插入图片描述

双向带头:结构最复杂,一般用来单独存储数据。
在这里插入图片描述

3.3 链表的实现

单向不带头
定义类型和结构体

typedef int LSdatatype;
typedef struct Slist
{
	LSdatatype data;
	struct Slist* next;
}SL;

在这里插入图片描述

在这里插入图片描述

//打印单链表
void SLprint(SL* phead);


void SLprint(SL* phead)
{
	SL* tmp = phead;
	while (tmp != NULL)
	{
		printf("%d->", tmp->data);
		tmp = tmp->next;
	}
	printf("NULL\n");
}
//销毁单链表
void SLdestory(SL* phead);


void SLdestory(SL** pphead)
{
	assert(pphead);
	SL* cur = *pphead;
	while (cur != NULL)
	{
		SL* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

在这里插入图片描述

由于每个节点中都保存下一个节点的地址,不能直接释放*pphead,需要创建临时变量进行替换。

插入数据,便需要创建一个新的节点,由于新节点的创建不止出现一次,为了方便,将其独立为函数

SL* CreateSLnode(LSdatatype x)
{
	SL* newnode = (SL*)malloc(sizeof(SL));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
//头插
void SLpushfront(SL** pphead, LSdatatype x);



void SLpushfront(SL** pphead, LSdatatype x)
{
	SL* newnode = CreateSLnode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

在这里插入图片描述

在这里插入图片描述

注意
改变数据,需要通过指针;改变指针,需要通过指针的指针。
由于上面是需要改变的指针,所有需要通过二级指针进行修改

在之后的学习中可以通过两种方式代替二级指针

  1. 返回新的链表头
  2. 设计为带哨兵位的链表
//尾插
void SLpushback(SL** pphead, LSdatatype x);


void SLpushback(SL** pphead, LSdatatype x)
{
	assert(pphead);
	SL* newnode = CreateSLnode(x);
	
	//1.plist 为空 改变结构体指针 
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	
	//2.plist 不为空  改变结构体内容
	else
	{   
	    //找尾
		SL* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

在这里插入图片描述

链表不为空,插入第一个节点,改变SL*,通过结构体指针的指针SL*pphead

链表为空,插入第一个节点,改变SL,通过结构体指针SL*tail

//头删
void SLpopfront(SL** pphead);


void SLpopfront(SL** pphead)
{
	assert(pphead);
	SL* del = *pphead;

	//检查,避免数据删除完之后,继续删除数据,导致内存崩溃
	//1 温柔的检查
	while (*pphead == NULL)
	{
		return;
	}

	//暴力检查
	/*assert(*pphead != NULL);*/

	*pphead = (*pphead)->next;
	free(del);
	del = NULL;
}

在这里插入图片描述

如果直接将第一个节点删去,就不能找到第二个节点,所以创建临时变量del保存第一个节点,之后再将其删去

//尾删
void SLpopback(SL** pphead);



void SLpopback(SL** pphead)
{
	assert(pphead);
	//1 温柔的检查
	while (*pphead == NULL)
	{
		return;
	}

	//暴力检查
	/*assert(*pphead != NULL);*/

	//1  一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	//2  多个节点
	else
	{
		方法1
		//SL* tail = *pphead;
		//while (tail->next->next != NULL)
		//{
		//	tail = tail->next;
		//}
		//free(tail->next);
		//tail->next = NULL;


		//方法2
		//找尾
		SL* tail = *pphead;
		SL* pre = NULL;
		while (tail->next != NULL)
		{
			pre = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		pre->next = NULL;
	}
}

在这里插入图片描述

//查找节点
SL* SLfind(SL* phead, LSdatatype x);




SL* SLfind(SL* phead, LSdatatype x)
{
	assert(phead);
	SL* cur = phead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}

		cur = cur->next;
	}

	return NULL;
}
//在pos之前插入新节点
void SLinsert(SL** pphead, SL* pos, LSdatatype x);


void SListInsert(SL** pphead, SL* pos, LSdatatype x)
{
	assert(pphead);
	assert(pos);


    //pos在第一个节点
	if (pos == *pphead)
	{
		SListPushFront(pphead, x);
	}
	else
	{
		SL* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;

			// 暴力检查,pos不在链表中,或者pos的值是错误的
			assert(prev);
		}

		SL* newnode = CreateSLnode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}

在这里插入图片描述

//在pos后面插入新节点
void SLinsertafter(SL* pos, LSdatatype x);


void SLinsertafter(SL* pos, LSdatatype x)
{
	assert(pos);
	SL* newnode = CreateSLnode(x);
	
	newnode->next = pos->next;
	pos->next = newnode;
}


在这里插入图片描述

//删除pos位置
void SLerase(SL* pphead, SL* pos);


void SLerase(SL** pphead, SL* pos)
{
	assert(pphead);
	assert(pos);

	//pos是第一个节点
	if (*pphead == pos)
	{
		SLpopfront(pphead);
	}
	else
	{
		SL* tmp = *pphead;
		while (tmp->next != pos)
		{
			tmp = tmp->next;
		}

		tmp->next = pos->next;
		free(pos);
		//不需要将pos置空,改变pos不会改变链表
		//pos=NULL
	}
}

在这里插入图片描述

//删除pos后面的位置
void SLeraseafter(SL* pos);


void SLeraseafter(SL* pos)
{
	assert(pos);
	if(pos->next != NULL)
	{
		SL* next = pos->next;
		next->next = pos->next;
		free(pos);
	}
	else
	{
		return;
	}
}

在这里插入图片描述

3.4 双向链表的实现

带头双向循环链表增删查改实现

定义类型和结构体

typedef int LTdatatype;

typedef struct LTlistnode
{
	struct LTlistnode* prev;
	struct LTlistnode* next;
	LTdatatype data;
}LTnode;

链表初始化

//链表初始化
LTnode* LTnodeinit();

LTnode* LTnodeinit()
{
	LTnode* guard = (LTnode*)malloc(sizeof(LTnode));
	if (guard == NULL)
	{
		perror("LTnodeinit fail");
		return;
	}
	guard->next = guard;
	guard->prev = guard;
	return guard;
}

在这里插入图片描述

链表尾插

与单链表类似,插入数据,创建一个新的节点,由于新节点的创建不止出现一次,为了方便,将其独立为函数

LTnode* Buynewnode(LTdatatype x)
{
	LTnode* newnode = (LTnode*)malloc(sizeof(LTnode));
	if (newnode == NULL)
	{
		perror("Buynewnode fail");
		return;
	}
	newnode->prev = NULL;
	newnode->next = NULL;
	newnode->data = x;

	return newnode;
}
//尾插
void LTnodepushback(LTnode* phead,LTdatatype x);

void LTnodepushback(LTnode* phead,LTdatatype x)
{

	assert(phead);

	LTnode* newnode = Buynewnode(x);
	LTnode* tail = phead->prev;
	tail->next = newnode;
	newnode->prev = tail;
	newnode->next = phead;
	phead->prev = newnode;
}

在这里插入图片描述

头插

//头插
void LTnodepushfront(LTnode* phead, LTdatatype x);

void LTnodepushfront(LTnode* phead, LTdatatype x)
{
	assert(phead);
	LTnode* newnode = Buynewnode(x);
	LTnode* next = phead->next;
	phead->next = newnode;
	newnode->prev = phead;
	newnode->next = next;
	next->prev = newnode;
}

在这里插入图片描述

计算链表长度

这里使用size_t较为合适,如果使用char类型来记录链表长度,当链表长度超过128时,便会出错

//计算链表长度
size_t LTsize(LTnode* phead);

size_t LTsize(LTnode* phead)
{
	assert(phead);
	LTnode* cur = phead->next;
	size_t n = 0;
	while (cur != phead)
	{
		n++;
		cur = cur->next;
	}
	return n;
}

判断链表是否为空

//判断链表是否为空
bool LTnodeempty(LTnode* phead);

bool LTnodeempty(LTnode* phead)
{
	assert(phead);
    //链表为空返回1,不为空返回0
	return phead->next == phead;
}

尾删

//尾删
void LTnodepopback(LTnode* phead);

void LTnodepopback(LTnode* phead)
{
	assert(phead);
	//链表不为空返回值为零,取反为真
	assert(!LTnodeempty(phead));
	LTnode* tail = phead->prev;
	LTnode* prev = tail->prev;

	phead->prev = prev;
	prev->next = phead;
}

在这里插入图片描述

头删

//头删
void LTnodepopfront(LTnode* phead);

void LTnodepopfront(LTnode* phead)
{
	assert(phead);
	//链表不为空返回值为零,取反为真
	assert(!LTnodeempty(phead));
	LTnode* prev = phead->next;
	LTnode* next = prev->next;
	phead->next = next;
	next->prev = phead;
}

在这里插入图片描述

链表查找

//链表查找
LTnode* LTnodefind(LTnode* phead,LTdatatype x);


LTnode* LTnodefind(LTnode* phead,LTdatatype x)
{
	assert(phead);
	LTnode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

链表插入,在pos前插入节点

//在pos前插入节点
void LTnodeinsert(LTnode* pos, LTdatatype x);

void LTnodeinsert(LTnode* pos, LTdatatype x)
{
	assert(pos);
	LTnode* prev = pos->prev;
	LTnode* newnode = Buynewnode(x);
	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = pos;
	pos->prev = newnode;
}

在这里插入图片描述

删除pos位置的节点

//删除节点
void LTnodeerase(LTnode* pos);


void LTnodeerase(LTnode* pos)
{
	assert(pos);
	LTnode* prev = pos->prev;
	LTnode* next = pos->next;
	prev->next = next;
	next->prev = prev;

	free(pos);
	pos = NULL;
}

在这里插入图片描述

打印链表

//打印链表
void LTnodeprint(LTnode* phead);

void LTnodeprint(LTnode* phead)
{
	assert(phead);
	printf("phead<=>");
	LTnode* cur = phead->next;

	while (cur != phead)
	{
		printf("%d<=>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

销毁链表

//销毁链表
void LTnodedestory(LTnode* phead);

void LTnodedestory(LTnode* phead)
{
	assert(phead);
	LTnode* cur = phead->next;
	while (cur != NULL)
	{
		LTnode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

4. 顺序表和链表的区别和联系

不同的顺序表链表
存储空间物理上一定连续逻辑上连续,物理上不一定连续
随机访问支持O(1)不支持O(N)
任意位置插入或删除元素可能需要挪动数据,效率低只需修改指针指向
插入动态顺序表,空间不够进行扩容没有容量的概念
应用元素高效存储+频繁访问任意位置插入或删除

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

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

相关文章

Qt 添加第三方字体库

Qt字体库默认主持操作系统所有的字体库&#xff0c;但是设计师一般喜欢比如思源字体&#xff0c;但是咱们的操作系统没有安装&#xff0c;在其他没有安装第三方字体库的电脑上运行&#xff0c;就达不到设计师最初设计的观感。这篇博客介绍Qt如何第三方字体库&#xff0c;以思源…

HTML【基础篇】

HTML【基础篇】&#x1f34e;一.HTML结构&#x1f352;1.1认识HTML标签&#x1f352;1.2HTML文件基本结构&#x1f352;1.3标签层次结构&#x1f352;1.4快速生成代码框架&#x1f34e;二.HTML常见标签&#x1f352;1.1注释标签&#x1f352;1.2标题标签&#xff08;h1-h6&…

用ADSelfService Plus更新Windows缓存的凭证

研究显示&#xff0c;帮助台技术员收到的所有电话中高达30%是因为遗忘了密码。当帮助台技术员处理大量此类电话时&#xff0c;对于来自远程的用户请求就无能为力了。这些用户使用本地缓存的Active Directory凭证来登录其机器。当该用户离开办公室时&#xff0c;帮助台技术员无法…

京东云开发者|ElasticSearch降本增效常见的方法

Elasticsearch在db_ranking 的排名又&#xff08;双叒叕&#xff09;上升了一位,如图1-1所示;由此可见es在存储领域已经蔚然成风且占有非常重要的地位。 随着Elasticsearch越来越受欢迎&#xff0c;企业花费在ES建设上的成本自然也不少。那如何减少ES的成本呢&#xff1f;今天…

某大厂软件测试岗一面笔试题+二面问答题面试经验分享

目录 某大软件测试厂笔试题 选择题 二面 某大软件测试厂笔试题 判断题(Y对&#xff0c;N错) 1.软件测试的目的是尽可能多的找出软件的缺陷。(Y) 2.Beta测试是验收测试的一种。(Y) 3.验收测试是由最终用户来实施的。(N) 4.项目立项前测试人员不需要提交任何工件。(Y) 5…

20 | 如何处理normal.mod not found

目录1 现象2 解决思路2.1 通过命令修复2.2 通过工具修复2.3 通过快照还原3 实际操作3.1 通过命令修复3.1.1 ls3.1.2 ls (hd0,X)/3.1.3 执行命令3.1.4 其他命令3.2 通过工具修复3.2.1 通过liveCD模式3.2.2 安装Boot-Repair3.2.3 修复3.3 通过快照还原1 现象 提示&#xff1a;ER…

YOLO9000: Better, Faster, Stronger (Yolov2)论文详细解读

目录前言1. Better&#xff08;更准&#xff09;2. Faster&#xff08;更快&#xff09;3. Stronger&#xff08;更壮&#xff09;前言 对应YOLOv1论文解读&#xff1a;You Only Look Once: Unified, Real-Time Object Detection&#xff08;Yolov1&#xff09; 论文详细解读 …

带你着手「Servlet」

⭐️前言⭐️ 有了前边文章为我们奠定下的网络基础&#xff0c;我们就可以开始学习Servlet的知识了&#xff0c;在部署一个Java的Servlet程序时&#xff0c;必须要有的开发工具是Tomcat,需要自行完成Tomcat的配置&#xff0c;并掌握maven仓库的配置方法&#xff0c;下边我们也…

windows下搭建mindspore的编译环境

rugwindows 10下安装mindpsore环境&#xff0c;需要visual studio 2019及以上&#xff0c;cmake, python 也可以从上面下载mindspore编译依赖的软件。 visual studioan安装时需注意 然后再安装cmake,git&#xff0c;安装好之后设置检查环境变量&#xff0c;缺失的要补上 系统…

WEB静态网页设计与制作——我的美丽家乡邢台

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

【数据结构】顺序表OJ

文章目录0. 前言1. 移除元素2. 删除有序数组中的重复项3. 合并两个有序数组4. 结语0. 前言 在上篇博客中&#xff0c;我们使用C语言实现了顺序表。其中我们也对顺序表的接口进行了完整的实现。但是光实现不够&#xff0c;还是需要题目来练习。于是今天我就为大家带来顺序表的三…

【雷达仿真 | FMCW TDMA-MIMO毫米波雷达信号处理仿真(可修改为DDMA-MIMO)】

本文编辑&#xff1a;调皮哥的小助理 本文引用了CSDN雷达博主XXXiaojie的文章源码&#xff08;https://blog.csdn.net/Xiao_Jie1&#xff09;&#xff0c;加以修改和注释&#xff0c;全面地、详细地阐述了FMCW TDM-MIMO毫米波雷达的工作原理&#xff0c;同时配套MATLA仿真实现方…

kubernetes

目录 一、容器云发展及主要内容 1、云平台计算,交付标准&#xff08;iaas-----openstack&#xff09; 2、平台即服务(PAAS&#xff09; 3.软件及服务(SAAS) 特点 二、内容 三、kubernetes集群架构与组件 基本组件 (1)Pod&#xff08;最小的资源单位&#xff09; (2)初…

信息系统综合测试与管理__软件测试

一 概念 软件测试是使用人工或者自动手机来运行或测试某个系统的过程&#xff0c; 目的是检测是否满足需求或者比较预期与实际的差别。 软件测试应该覆盖整个开发、维护过程&#xff0c; 不仅仅是编码阶段完成之后进行的一项活动。 常考的软件测试工具为LoadRunner, 是一种…

RHCE——分区、创建逻辑卷

1.创建一个逻辑卷 请按下列要求创建一个新的逻辑卷&#xff1a; 创建一个名为 datastore 的卷组&#xff0c;卷组的大小为4G 逻辑卷的名字为 database ,所属卷组为 datastore,该逻辑卷大小为3G 将新建的逻辑卷格式化为 xfs 文件系统&#xff0c; 2.通过自动挂载将该逻辑卷到/v…

机器学习笔记 十五:随机森林(Random Forest)评估机器学习模型的特征重要性

随机森林1. 随机森林介绍1.1 租赁数据案例2. 特征相关性分析&#xff08;热图&#xff09;2.1 热图绘制2.2 构建随机森林模型2.3 不同特征合并的重要性2.3.1 经纬度合并&#xff08;分3类&#xff09;2.3.2 经纬度合并&#xff08;分2类&#xff09;2.3.3 经纬度合并&#xff0…

HTML CSS游戏官网网页模板 大学生游戏介绍网站毕业设计 DW游戏主题网页模板下载 游戏娱乐网页成品代码...

✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f947; 关于作者: 历任研发工程师&#xff0c;技术组长&#xff0c;教学总监。 十载寒冰&#xff0c;难凉热血&#xff1b;多年过去&#xff0c;历经变迁&#xff0c;物是人非。 然而&#xff0c;对于技术的探索…

系分 - 系统规划

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 系分 - 系统规划 考点摘要 系统规划的步骤&#xff08;★&#xff09;可行性分析&#xff08;★★★&#xff09;成本效益分析&#xff08;★★★&#xff09; 系统规划的步骤 初步调查根据企业战略目标&#…

一行行的代码解密马尔可夫链

使用Python的马尔科夫链实例的实践 一行行的代码解密马尔可夫链。 当我开始学习物理时&#xff0c;我并不喜欢概率的概念。我对用物理学可以对整个世界进行建模的想法非常振奋&#xff0c;不确定性的想法让我很生气:) 事实是&#xff0c;当我们想研究真实的现象时&#xff0c;我…

硬件电路(3)设计篇----为什么栅极型推挽电路不用上P下N?

在做信号控制以及驱动时&#xff0c;为了加快控制速度&#xff0c;经常要使用推挽电路。推挽电路可以由两种结构组成&#xff1a;分别是上P下N&#xff0c;以及上N下P。其原理图如下所示&#xff0c; 在平时中&#xff0c;我个人经常遇到的推挽电路是第一种。当我每次问身边的…