【数据结构入门】-链表之单链表(1)

news2024/10/7 4:31:33

个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【数据结构初阶(C实现)】
在这里插入图片描述

文章标题

  • 回顾
  • 链表
    • 链表的概念及结构
  • 各种节点
    • 打印链表
    • 尾插
    • 创建节点
    • 尾删
    • 头插
    • 头删
    • 查找
    • 在pos之前去插入
    • 在pos之后去插入
    • 删除pos位置的值
    • 销毁链表
  • 总代码
    • test.c
    • Slist.c
    • Slist.h

回顾

在讲解链表之前我们先来看看顺序表有哪些缺陷呢?

1.空间不够需要增容,而增容就需要付出代价,realloc增容(一种是原地扩容,另一种是异地扩容)时会容易产生内存碎片(异地扩容时)。
2.顺序表为了频繁扩容,所以空间一旦满了基本上就是扩2倍,可能会存在空间的浪费(因为扩出来的空间可能用不了那么多)。
3.顺序表要求数据从头开始位置连续存储,那么我们在头部或者中间位置插入删除数据就需要挪动数据,效率不高。

realloc原地扩容:

int main()
{
	int* p1 = (int*)malloc(10 * sizeof(int));
	int* p2 = (int*)realloc(p1, 11 * sizeof(int));

	return 0;
}

在这里插入图片描述
realloc(异地扩容)

#include<stdlib.h>

int main()
{
	int* p1 = (int*)malloc(10 * sizeof(int));
	int* p2 = (int*)realloc(p1, 1000 * sizeof(int));

	return 0;
}

在这里插入图片描述

链表

针对顺序表存在的一些缺陷,所以就设计出来了链表。然而顺序表也并不是一无是处,对于顺序表是一块连续的空间,只需要存储第一个空间的地址,就可以找到所有的数据(对于这种物理上是连续的好处,比如a[i]等价于*(a+i))。
而对于链表倘若要遍历所有的数据,就需要通过指针来进行链接(第一个存第二个的地址、第二个存第三个的地址、第三个存第四个的地址…),所以这也是链表的代价,每存储一个数据就需要伴随一个指针,即每个数据都要存一个指针去链接后面数据节点不支持随机访问(用下标直接访问第i个)
同时链表一定程度上也更好的解决了顺序表头部、中间插入数据时还需要挪动数据。链表就不需要这么麻烦,只需要改指针的链接,不需要挪动数据
这里指的是单链表,当然链表不仅仅只是这一种结构,我们先从最简单的单链表开始,循序渐进。

链表的概念及结构

概念:链表是一种物理存储结构上非连接、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,可以根据自己的需要按需申请空间。

typedef int SLTDateType;

struct SListNode
{
	SLTDateType data;//data就是我们要存储的数据
	struct SListNode* next;
};

各种节点

void SListPrint(SLTNode* phead);

void SListPushBack(SLTNode** pphead,SLTDateType x);

void SListPustFront(SLTNode** pphead, SLTDateType x);

void SListPopBack(SLTNode** pphead);

void SListPopFront(SLTNode** pphead);

SLTNode* SListFind(SLTNode* phead, SLTDateType x);//查找

//在pos位置之前去插入一个节点
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x);//某个位置插入
//void SListInsert(SLTNode* phead, int pos, SLTDateType x);//某个位置插入

void SListInsertAfter(SLTNode* pos, SLTDateType x);

void SListErase(SLTNode** pphead, SLTNode* pos);
//void SListErase(SLTNode** phead, int pos);

void SListEraseAfter( SLTNode* pos);

void SListDestory(SLTNode** pphead);//销毁链表

打印链表

首先,phead是一个结构体指针指向第一个节点,cur也是如此,循环打印每个节点的数据就是通过cur = cur->next;走下去的,直到cur为空指针为止
在这里插入图片描述

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

尾插

//尾插
void SListPushBack(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);
	SLTNode* newnode = BuyListNode(x);

	//起初链表中是啥也没有的
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//找到尾部=节点
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

注意:第一种情况:倘若链表中起初啥也没有的,所以就需要我们先创建一个节点。
第二种情况:此时链表中是有数据的,此时我们要想尾插一个尾节点,就需要先找到尾。找到尾部节点的空指针后,直接把此空指针置为新节点的指针(即tail->next = newnode;)。
我们发现,即使链表是否为空,我们都需要新创建一个节点。所以我们专门分装一个专门创建一个节点的函数,并把这个节点的地址返回就好了。这样我们也方便以后头插等情况时候创建新节点。
还有一个点需要注意,请看这里:void SListPushBack(SLTNode** pphead, SLTDateType x),我们在进行尾插的时候为什么要传二级指针过去呢?这的确是一个值得思考的问题。当我们想要进行尾插即SListPushBack(&plist, 1); SListPushBack(&plist, 2);的时候,如果我们不传plist的地址的话,那么在尾插函数(SListPushBack)内部pphead的改变是无法改变外部的plist的。所以我们就需要传plist的地址过去,此时我们也就需要二级指针来进行接收(因为plist本身就是一个指针)。
总之我们如果想改变plist的值的话,就需要将其地址传过去,否则形参就是实参的一份临时拷贝,形参的改变是无法改变实参的。

创建节点

SLTNode* BuyListNode(SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));

	//检查是否开辟成功
	if (newnode == NULL)
	{
		printf("malloc fail\n");//内存申请失败的话说明已经没有多少空间了
		exit(-1);//申请失败则直接结束程序
	}

	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

尾删

void SlistPopBack(SLTNode** pphead)
{
	//温柔一点
	if (*pphead == NULL)
	{
		return;
	}

	//粗暴一点
	//assert(*pphead != NULL);

	//走到这里意味着一定有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pphead;

		//while (tail->next != NULL)
		while (tail->next)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;

		prev->next = NULL;
	}
}

进行尾删时总共三种情况:第一,链表为空;第二,链表只要一个节点;第三,链表有1个以上的节点。
这里我们来看一下最复杂的情况(第三种):当链表有一个以上的节点时,当我们尾删链表的最后一个节点时,我们还需要把最后一个链表的前一个链表的next置为空指针,否则其就变成了野指针。但是由于单链表是无法找到前一个节点的next指针的。所以我们定义一个prev,在tail往下走(即tail = tail->next;)之前先进行prev = tail;。另外tail置不置空无所谓,因为出了tail的作用域其就被销毁了。

头插

void SListPustFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);

	newnode->next = *pphead;
	*pphead = newnode;
}

头删

void SListPopFront(SLTNode** pphead)
{
	//空
	//一个节点
	//一个以上节点
	assert(pphead);
	//处理一个或者多个节点都可以,但是唯独不能处理节点为空
	/*if (*pphead == NULL)
	{
		return;
	}*/
	assert(*pphead != NULL);//节点为空直接报错
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
	//实际上我们可以把一个节点或者一个以上节点进行统一处理。
}

这里我们先明确一个问题,问题1:free()释放的是指针呢?还是释放的是内存呢?应该是这样的:free释放的是指针指向的内存。
问题2:内存泄漏是内存丢了还是指针丢了?应该是这样的:内存泄漏是指针丢了,我们直到如果指针在的话(可以找到)我们依然可以随时释放指针指向的空间;但是如果指针真的丢了(找不到了)那我们连哪些内存没有释放都不知道。内存是不会丢的,因为内存一直是在那个位置,free只是把这块空间的使用权还给系统,同时把这块空间置为随机值。

查找

查找返回的是一个指针。

SLTNode* SListFind(SLTNode* phead, SLTDateType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;//来到这里说明到最后都没有找到,返回空
}

在pos之前去插入

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	assert(pphead);
	assert(pos);
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)
	{
		//相当于头插了,可以调用其函数
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else
	{
		//找到pos的前一个位置
		SLTNode* posPrev = *pphead;
		while (posPrev->next != pos)
		{
			posPrev = posPrev->next;
		}
		posPrev->next = newnode;
		newnode->next = pos;
	}
}

在pos之后去插入

void SListInsertAfter(SLTNode* pos, SLTDateType x)
{
	assert(pos);
	SLTNode* newnode = BuyListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

注意:顺序不要颠倒()newnode->next = pos->next; pos->next = newnode;

删除pos位置的值

void SListErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	if (*pphead == pos)
	{
		//相当于头删
		/**pphead = pos->next;
		free(pos);*/
		SListPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

销毁链表

void SListDestory(SLTNode** pphead)//销毁链表
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

总代码

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"

void TestSList1()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);

	SListPrint(plist);

	

	SListPushFront(&plist, 1);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 4);

	SListPrint(plist);

}

void TestSList2()
{
	SLTNode* plist = NULL;
	
	SListPushFront(&plist, 1);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 4);

	SlistPopBack(&plist);

	SListPrint(plist);

}

void TestSList3()//测试头删
{
	SLTNode* plist = NULL;

	SListPushFront(&plist, 1);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 4);

	SListPopFront(&plist);
	SListPrint(plist);

	SListPopFront(&plist);
	SListPrint(plist);

	SListPrint(plist);

	SListPopFront(&plist);
	SListPrint(plist);
}

void TestSList4()//测试查找
{
	SLTNode* plist = NULL;

	SListPushFront(&plist, 1);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 4);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 4);
	SListPrint(plist);

	//找
	SLTNode* pos = SListFind(plist, 2);
	int i = 1;
	while (pos)
	{
		printf("第%d个pos节点:%p->%d\n", i++, pos, pos->data);
		pos = SListFind(pos->next, 2);
	}

	//修改3->30
	pos = SListFind(plist, 3);
	if (pos)
	{
		pos->data = 30;
	}
	SListPrint(plist);
}

void TestSList5()//测试查找
{
	SLTNode* plist = NULL;

	SListPushFront(&plist, 1);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 4);
	SListPrint(plist);

	SLTNode* pos = SListFind(plist, 3);
	if (pos)
	{
		SListInsert(&plist, pos, 30);
	}
	SListPrint(plist);

	pos = SListFind(plist, 1);
	if (pos)
	{
		SListInsert(&plist, pos, 10);
	}
	SListPrint(plist);

	pos = SListFind(plist, 4);
	if (pos)
	{
		SListInsert(&plist, pos, 40);
	}
	SListPrint(plist);

}
TestSList6()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);

	SListPrint(plist);
	SListDestory(&plist);//销毁链表

}
int main()
{
	//TestSList1();
	//TestSList2();
	//TestSList3();
	//TestSList4();
	//TestSList5();
	TestSList6();
	return 0;
}

Slist.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"SList.h"

SLTNode* BuyListNode(SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));

	//检查是否开辟成功
	if (newnode == NULL)
	{
		printf("malloc fail\n");//内存申请失败的话说明已经没有多少空间了
		exit(-1);//申请失败则直接结束程序
	}

	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

//尾插
void SListPushBack(SLTNode** pphead, SLTDateType x)
{
	assert(pphead);
	SLTNode* newnode = BuyListNode(x);

	//起初链表中是啥也没有的
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//找到尾部=节点
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

//头插
void SListPushFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);

	newnode->next = *pphead;
	*pphead = newnode;
}

//头删
void SlistPopBack(SLTNode** pphead)
{
	//温柔一点
	if (*pphead == NULL)
	{
		return;
	}

	//粗暴一点
	//assert(*pphead != NULL);

	//走到这里意味着一定有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pphead;

		//while (tail->next != NULL)
		while (tail->next)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;

		prev->next = NULL;
	}
}

void SListPopFront(SLTNode** pphead)
{
	//空
	//一个节点
	//一个以上节点
	assert(pphead);
	//处理一个或者多个节点都可以,但是唯独不能处理节点为空
	/*if (*pphead == NULL)
	{
		return;
	}*/
	assert(*pphead != NULL);//节点为空直接报错
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

SLTNode* SListFind(SLTNode* phead, SLTDateType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;//来到这里说明到最后都没有找到,返回空
}

//在pos位置之前去插入一个节点
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	assert(pphead);
	assert(pos);
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)
	{
		//相当于头插了,可以调用其函数
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else
	{
		//找到pos的前一个位置
		SLTNode* posPrev = *pphead;
		while (posPrev->next != pos)
		{
			posPrev = posPrev->next;
		}
		posPrev->next = newnode;
		newnode->next = pos;
	}
}

//在pos之后去插入,更合适,也更简单
void SListInsertAfter(SLTNode* pos, SLTDateType x)
{
	assert(pos);
	SLTNode* newnode = BuyListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

void SListErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	if (*pphead == pos)
	{
		//相当于头删
		/**pphead = pos->next;
		free(pos);*/
		SListPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

//删除后一个
void SListEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);//报错就说明你用错来
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
	//next = NULL;//置不置空没有意义
}

void SListDestory(SLTNode** pphead)//销毁链表
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

Slist.h

#define _CRT_SECURE_NO_WARNINGS 1

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

typedef int SLTDateType;

typedef struct SListNode
{
	SLTDateType data;//data就是我们要存储的数据
	struct SListNode* next;
}SLTNode;

void SListPrint(SLTNode* phead);

void SListPushBack(SLTNode** pphead,SLTDateType x);

void SListPushFront(SLTNode** pphead, SLTDateType x);

void SListPopBack(SLTNode** pphead);

void SListPopFront(SLTNode** pphead);

SLTNode* SListFind(SLTNode* phead, SLTDateType x);//查找



//在pos位置之前去插入一个节点
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x);//某个位置插入
//void SListInsert(SLTNode* phead, int pos, SLTDateType x);//某个位置插入

void SListInsertAfter(SLTNode* pos, SLTDateType x);

void SListErase(SLTNode** pphead, SLTNode* pos);
//void SListErase(SLTNode** phead, int pos);

void SListEraseAfter( SLTNode* pos);

void SListDestory(SLTNode** pphead);//销毁链表

以上就是单链表的基本操作,就到这里吧,再见啦!!!
在这里插入图片描述

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

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

相关文章

微信小程序 Vue+uniapp+nodejs早教育教幼教知识学习系统

目 录 1绪论 1 1.1项目研究的背景 1 1.2开发意义 1 1.3项目研究现状及内容 5 1.4论文结构 5 2开发技术介绍 7 2.5微信小程序技术 8 3系统分析 9 3.1可行性分析 9 3.1.1技术可行性 9 3.1.2经济可行性 9 3.1.3操作可行性 10 3.2网站性能需求分析 10 3.3网站功能分析 10 3.4系统…

PHP7.4 FFI 扩展安全问题

在前面 [极客大挑战 2020] 的Roamphp5-FighterFightsInvincibly 题&#xff0c;遇到了 FFI扩展 调用函数进行rce to bypass disable_function&#xff0c;之前没遇见过&#xff0c;刚好借此机会学一学 目录 <1> PHP 7.4 FFI简介 <2> FFI 配置信息 <3> FF…

数据库丨TiDB集群中高危Grafana权限漏洞如何快速修复?答案在这里→

文章目录前言一、现有TiDB信息二、下载解压Grafana组件1.下载2. 解压安装三、制作离线镜像源1.制作镜像2.离线镜像发布3.查看当前镜像源&#xff0c;设置镜像源境准备4.备份private.json5.publish镜像6.各个参数解释如下&#xff1a;7.清理老文件四、Grafana组件升级替换Grafan…

记数据血缘前端中panzoom初始化缩放比例的问题探索

0. 背景 有人问我 血缘前端vue版本能不能改初始缩放比例&#xff0c;节点太多的情况下初始缩放比例太大导致无法看清全图&#xff0c;需要渲染完之后手动缩放才能。 当时编写代码的时候使用 panzoom这个库来完成 血缘图的缩放工作。 使用的panzoom版本是&#xff1a; “panzoo…

nacos启动失败(解决方法汇总)

安装nacos 报错 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name instanceOperatorClientImpl defined in URL [jar:file:/H:/nacos/nacos/target/nacos-server.jar!/BOOT-INF/lib/nacos-naming-2.0.3.jar!/com/alibaba/na…

【数据结构与算法】哈希表2:四数相加II 赎金信 三数之和 四数之和

文章目录今日任务1.Leetcode454.四数相加II&#xff08;1&#xff09;题目&#xff08;2&#xff09;思路&#xff08;3&#xff09;代码演示2.Leetcode383.赎金信&#xff08;1&#xff09;题目&#xff08;2&#xff09;思路&#xff08;3&#xff09;暴力解法&#xff08;4&…

算法刷题日志——移除元素,双指针

文章目录删除有序数组中的重复项[删除有序数组中的重复项 II](https://leetcode.cn/problems/remove-duplicates-from-sorted-array-ii/)移除元素[283. 移动零](https://leetcode.cn/problems/move-zeroes/description/)[844. 比较含退格的字符串](https://leetcode.cn/problem…

数仓、数据湖、湖仓一体、数据网格的探索与研究

第一代&#xff1a;数据仓库 定义 为解决数据库面对数据分析的不足&#xff0c;孕育出新一类产品数据仓库。数据仓库&#xff08;Data Warehouse&#xff09;是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合&#xff0c;用于支持管理决策和信息的全局共享。 数…

【Linux系统】认识操作系统和操作系统如何进行管理以及进程相关状态

进程概念1 认识冯诺依曼体系结构1.1 冯诺依曼体系结构存储器的作用2 操作系统(Operator System&#xff0c;OS)2.1 OS如何进行管理3 进程3.1 OS管理进程&#xff1a;先描述再组织3.2 描述进程-PCB3.3 查看进程3.4 通过系统调用获取进程标识符3.5 通过系统调用创建子进程——for…

vue+echarts:柱状图横向展示和竖向展示

第021个点击查看专栏目录本示例是显示柱状图&#xff0c;分别是横向展示和纵向展示。关键是X轴和Y轴的参数互换。 文章目录横向示例效果横向示例源代码&#xff08;共81行&#xff09;纵向示例效果纵向示例源代码&#xff08;共81行&#xff09;相关资料参考专栏介绍横向示例效…

什么是真正的骨传导耳机,骨传导耳机原理

骨传导耳机大多采用后挂耳/夹耳佩戴方式&#xff0c;但现在很多人分不清哪些是骨传导耳机&#xff0c;哪些是气传导耳机。看完这篇教会你辨别哪些是真正的骨传导耳机。 骨传导耳机采用固体传声方式&#xff0c;整个耳机机身都没有传声音孔的设计&#xff0c;主要通过耳机振子发…

Retrofit+Hilt后端请求小项目3--Retrofit代码完善

目录ApiConstants定义实体类定义 API 接口定义 Repository定义 ApiModule定义 Application定义 ViewModelApiConstants 这一块存放 API 常量&#xff0c;即后端服务器 BASE_URL&#xff0c;以及对应的后缀 URL 代码清单&#xff1a;data/api/ApiConstants.kt object ApiConsta…

最纯净-Ubuntu系统下如何卸载kubernetes(k8s)-2023最新

首先&#xff0c;如果是卸载k8s-1.24以上版本&#xff0c;需要单独卸载containerd&#xff1a; sudo apt-get purge --auto-remove containerd.io1. 步骤 其他步骤如下&#xff1a; 执行命令&#xff1a; kubeadm reset -fsudo apt-get purge --auto-remove kubernetes…

港科夜闻|广东省省长王伟中会见香港科技大学访问团

关注并星标每周阅读港科夜闻建立新视野 开启新思维1、广东省省长王伟中会见香港科技大学访问团。2月17日&#xff0c;广东省省长王伟中先生在广州与香港科大校董会主席廖长城先生、校董会副主席杨佳锠教授、校长叶玉如教授就加强教育合作、科技创新等进行深入交流。王伟中先生表…

华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】

刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…

特征与处理-sklearn归一化、标准化、缺失值处理

目录 特征的预处理 归一化 标准化 缺失值 特征的预处理 特征处理定义&#xff1a;通过特定的二统计方法&#xff08;数学方法&#xff09;将数据转换成算法要求的数据 归一化 sklearn归一化API&#xff1a;sklearn.preprocessing.MinMaxScaler from sklearn.preprocessing i…

【Selenium学习】Selenium 总结

1.Selenium 简介Selenium 经历了三个大版本&#xff0c;Selenium 1.0、Selenium 2.0 和 Selenium 3.0。Selenium 不是由单独一个工具构成的&#xff0c;而是由一些插件和类库组成的&#xff0c;这些插件和类库有其各自的特点和应用场景。Selenium 1.0 家族关系如下图所示。1.1 …

华为OD机试 - 数组排序(C++) | 附带编码思路 【2023】

刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…

我说我为什么抽不到SSR,原来是这段代码在作祟...

本文是龚国玮所写&#xff0c;熊哥有所新增修改删减&#xff0c;原文见文末。 我说我为什么抽不到SSR&#xff0c;原来是加权随机算法在作祟 阅读本文需要做好心理准备&#xff0c;建议带着深究到底的决心和毅力进行学习&#xff01; 灵魂拷问 为什么有 50% 的几率获得金币&a…

【数据结构】顺序表和链表的区别和联系(详解)

顺序表和链表的区别&#xff08;详解&#xff09; 文章目录顺序表和链表的区别&#xff08;详解&#xff09;前言一、顺序表和链表的关系二、顺序表1.优点2.缺点三、链表1.优点2.缺点四、区别表格总结前言 本文给大家介绍顺序表和链表的各自的优缺点和区别与联系&#xff0c;结…