手撕无头单链表


  • 💓 博客主页:江池俊的博客
  • ⏩ 收录专栏:数据结构探索
  • 👉专栏推荐:✅C语言初阶之路 ✅C语言进阶之路
  • 💻代码仓库:江池俊的代码仓库
  • 🔥编译环境:Visual Studio 2022
  • 🎉欢迎大家点赞👍评论📝收藏⭐

在这里插入图片描述

文章目录

  • 🚨一、什么是链表
    • 1.1 链表的概念
    • 1.2 链表的分类
  • 🚨二、单链表的结构
  • 🚨三、单链表的创建
    • 3.1 单链表的存储结构
    • 3.2 单链表的接口
  • 🚨四、接口实现(增、删、查、改)
    • 4.1 单链表的插入
      • 🔥前提:向内存申请节点空间
      • 📌尾插
      • 📌头插
      • 📌在pos节点之前插入x
      • 📌在pos节点以后插入x
    • 4.2 单链表的删除
      • ♨️尾删
      • ♨️头删
      • ♨️删除pos节点
      • ♨️删除pos的后一个节点
    • 4.3 单链表的其他接口实现
      • 🌟打印单链表
      • 🌟查找
      • 🌟单链表的销毁
  • 🚨五、源码
    • 5.1 `SList.h` 文件
    • 5.2 `SList.c` 文件
    • 5.3 `Test.h` 文件


🚨一、什么是链表

1.1 链表的概念

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

1.2 链表的分类

链表主要有单向、双向、带头节点、不带头节点、循环和非循环这些特点,再经过它们的互相组合就形成了 2 × \times × 2 × \times × 2 = 8种链表的结构。

此处我要讲解的是 不带头单向非循环 链表。


🚨二、单链表的结构

单向链表(又名单链表、线性链表) 是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过从头部开始,依序往下读取。

一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。

在这里插入图片描述

前面我们学习了顺序表,这里我们先来分析一下顺序表和单链表的优缺点:

顺序表:

优点:

  1. 访问元素时,顺序表可以在常数时间内完成(O(1)),无论数据量多大。
  2. 顺序表可以利用缓存和预读取技术进行优化,以提高访问速度。
  3. 对于随机访问和快速查找操作,顺序表通常比单链表更高效。

缺点:

  1. 顺序表在插入和删除操作上较慢,因为可能需要移动大量的元素来保持数据的连续性。这些操作的平均时间复杂度为O(n),其中n是元素的数量。
  2. 顺序表通常需要连续的内存空间,因此当数据量非常大时,可能会面临内存分配的问题。
  3. 在顺序表中查找特定元素可能需要遍历整个数组,这在处理大量数据时可能会变得很慢。

单链表:

优点:

  1. 插入和删除操作在链表的前端和后端相对较快,时间复杂度为O(1)。
  2. 内存使用效率较高,因为每个节点只存储一个指向下一个节点的引用。
  3. 对于一些特定的问题,如反转链表或找到链表中倒数第k个元素等,单链表有较好的解决方案。

缺点:

  1. 访问链表的中间元素需要从头部开始遍历,时间复杂度为O(n),其中n是链表的长度。
  2. 在大规模数据中,查找操作可能比其他数据结构(如数组或哈希表)慢。
  3. 由于需要额外的空间来存储指针,所以内存使用量比顺序表大。

🚨三、单链表的创建

3.1 单链表的存储结构

typedef int SLTDataType;//定义数据类型的别名,方便后续存储元素类型改变的修改

//定义结点类型 
typedef struct SListNode
{
	SLTDataType data;//每个节点存放一个数据元素
	struct SListNode* next;//结构体指针,指向下一个节点
}SLTNode;

3.2 单链表的接口

// 动态申请一个节点
SLTNode* BuySListNode(SLTDataType x);
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SLTPopBack(SLTNode** pphead);
//头删
void SLTPopFront(SLTNode** pphead);
//打印单链表
void SLTPrint(SLTNode* phead);
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
// 在pos节点之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
// 在pos节点以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
// 删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);
// 删除pos的后一个节点
void SLTEraseAfter(SLTNode* pos);
//单链表的销毁
void SLTDestroy(SLTNode** pphead);

🚨四、接口实现(增、删、查、改)

4.1 单链表的插入

  • 在插入节点之前我们首先需要动态申请一个节点来保存要插入的数据,并将此节点放在相应的位置。
  • 而申请节点的操作在所有插入函数中都需要进行,故我们可以将这个操作写成一个申请节点的函数,方便各种插入函数的调用。

🔥前提:向内存申请节点空间

// 动态申请一个节点
SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x; 
	newnode->next = NULL;
	return newnode;
}

在这里插入图片描述

📌尾插

注意:

  1. 特殊情况,当链表为空时,则需要更改链表的头指针的地址,使得它的指向不再是 NULL,而是插入的新的节点的地址。
  2. 这里需要修改链表的头指针的地址,所以在传参的时候需要传入链表头指针的地址,即接收它的形式参数为二级指针。
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	if (*pphead == NULL) 
	{
		*pphead = newnode;//改变了结构体指针,所以传二级指针
	}
	else
	{
		SLTNode* tail = *pphead; 
		while (tail->next) 
		{ 
			tail = tail->next; 
		}
		tail->next = newnode;//改变的结构体,用结构体的指针即可
	}
}

📌头插

头插的算法比较简单,只需要将新节点的next指向链表的头,然后修改链表的头为新节点即可。即使链表为空时此算法依然成立。

//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	
	newnode->next = *pphead; 
	*pphead = newnode; 
}

📌在pos节点之前插入x

这里我们需要保存 pos 节点之前那个节点的位置,所有使用一个临时结构体指针变量 prev来保存前一个节点的位置,然后将新的节点插入其中即可。

注意:

  • 特殊情况,当 pos 节点等于链表的头节点时,就需要进行头插的操作,将新的节点插入到链表的头节点之前,然后将新节点置为链表的头。
// 在pos节点之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	//要么都是空,要么都不是空 --- 当链表不为空时,pos不能为空
	//当链表为空,则pos必须为空
	//总结;pos一定要为有效节点,NULL不是有效节点
	//assert((!pos && !(*pphead)) || (pos && *pphead));

	assert(pos);//pos不为空
	assert(*pphead);//链表不为空
	SLTNode* newnode = BuySListNode(x); 

	if (*pphead == pos)
	{
		//头插
		newnode->next = *pphead;  
		*pphead = newnode; 
	}
	else
	{
		SLTNode* prev = *pphead;//用来保存pos前面的那个节点
		while (prev->next != pos) 
		{
			prev = prev->next; 
		}
		prev->next = newnode; 
		newnode->next = pos;  
	}
}

📌在pos节点以后插入x

因为是在 pos 之后插入,所以自动的 pos 极为插入位置的前一个节点,于是只要把新的节点插入到 pos 节点之后即可。

注意:

  • pos 不能为 NULL,因为 NULL 后面无法再插入节点
// 在pos节点以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuySListNode(x); 
	newnode->next = pos->next; 
	pos->next = newnode;
}

4.2 单链表的删除

♨️尾删

删除节点操作,首先要确保链表不为空。其次,就是当链表中只有一个节点时,删除链表后,链表变成空,此时链表的头需要置为空。

//尾删
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead&&*pphead);//没有节点不需要删除
	//1.一个节点的删除
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else//2.多个节点的删除
	{
	    //第一种删除方式
		//SLTNode* prev = NULL; 
		//SLTNode* tail = *pphead; 
		//while (tail->next != NULL)
		//{
		//	prev = tail;
		//	tail = tail->next;
		//}
		//free(tail);
		//tail = NULL;//tail是局部变量,不置空也可以,因为出了作用域tail就销毁了
		//prev->next = NULL;
		
		//第二种删除方式	
		SLTNode* tail = *pphead;
		while (tail->next->next != NULL)
		{
			tail = tail->next; 
		}
		free(tail->next);
		tail->next = NULL; 
	}
}

♨️头删

头删也需要确保链表不为空,其次就是正常的删除节点的操作,当只有一个节点时,仍然满足逻辑。

//头删
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead && *pphead);
	SLTNode* cur = (*pphead)->next; 
	free(*pphead); 
	*pphead = cur; 
}

♨️删除pos节点

  1. 首先,确保链表不为空
  2. 其次,判断链表的头节点是否为要删除的节点:
    • 如果是,则将链表的头节点置为此时头节点的 next
    • 如果不是,则用一个 prev 节点来保存 pos 节点的前一个节点的位置,通过 while 循环找到此节点。
// 删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead);
	assert(pos);
	if (*pphead == pos)
	{
		//头删
		*pphead = pos->next;
		free(pos);
		pos = NULL;
	}
	else
	{
		SLTNode* prev = *pphead;//用来保存pos节点之前的节点地址
		while (prev->next != pos) 
		{
			prev = prev->next; 
		}
		prev->next = pos->next; 
		free(pos); 
		pos = NULL; 
	}
}

♨️删除pos的后一个节点

个操作比较简单,因为要删除的节点的位置的前一个节点即为 pos,所以在进行删除的时候只需要保存要删除的节点,再让 pos
next 指向 posnextnext ,最后 free 掉保存的这个要删除的节点即可。

注意:

  • 这里需要确保 pos 节点不为空且 posnext 也不为空。
// 删除pos的后一个节点
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next);
	SLTNode* cur = pos->next;
	pos->next = cur->next;
	free(cur);
}

4.3 单链表的其他接口实现

🌟打印单链表

此算法只需要遍历一遍单链表,并将每个节点中存储的值打印出来即可,在循环外最好加上打印 NULL 的语句,便于直观的看出链表的结构。

//打印单链表
void SLTPrint(SLTNode* phead)
{
	while (phead)
	{
		printf("%d->", phead->data);
		phead = phead->next;
	}
	printf("NULL\n");
}

🌟查找

同理,只需要遍历链表即可。

//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{//空链表可以查找
	while (phead)
	{
		if (phead->data == x)
		{
			return phead; 
		}
		phead = phead->next; 
	}
	return NULL;//链表为空找不到
}

🌟单链表的销毁

  1. 首先,通过assert(pphead);确认传入的链表头指针不为空,如果为空则程序会中断。
  2. 然后,定义两个指针prevcur,其中prev指向当前节点的前一个节点,cur指向当前节点。初始时,prev为空,cur指向链表的头节点。
  3. 使用一个循环遍历链表。在循环中,首先将prev指向当前节点,然后将cur指向下一个节点。然后释放prev指向的节点的内存空间,并将prev置为空。
  4. 循环直到cur为空,即遍历完整个链表。此时,prev将会指向链表的最后一个节点。
  5. 最后,将链表的头指针设置为空,即*pphead = NULL;,表示链表已经销毁。然后输出"单链表销毁成功"。

整个过程就是从链表的头部开始,逐个释放节点的内存空间,直到链表的尾部,完成整个链表的销毁。

//单链表的销毁
void SLTDestroy(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* prev = NULL;
	SLTNode* cur = *pphead;
	while (cur)
	{
		prev = cur;
		cur = cur->next;
		free(prev);
		prev = NULL;
	}
	*pphead = NULL;
	printf("单链表销毁成功\n");
}

🚨五、源码

5.1 SList.h 文件

#pragma once

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

typedef int SLTDataType;//定义数据类型的别名,方便后续存储元素类型改变的修改

//定义结点类型 
typedef struct SListNode
{
	SLTDataType data;//每个节点存放一个数据元素
	struct SListNode* next;//结构体指针,指向下一个节点
}SLTNode;

// 动态申请一个节点
SLTNode* BuySListNode(SLTDataType x);

//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);

//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);

//尾删
void SLTPopBack(SLTNode** pphead);

//头删
void SLTPopFront(SLTNode** pphead);

//打印单链表
void SLTPrint(SLTNode* phead);


//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);

// 在pos节点之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);

// 在pos节点以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);

// 删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);

// 删除pos的后一个节点
void SLTEraseAfter(SLTNode* pos);

//单链表的销毁
void SLTDestroy(SLTNode** pphead);

5.2 SList.c 文件

#define _CRT_SECURE_NO_WARNINGS 1

#include "SList.h"

// 动态申请一个节点空间
SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x; 
	newnode->next = NULL;
	return newnode;
}

//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	if (*pphead == NULL) 
	{
		*pphead = newnode;//改变了结构体指针,所以传二级指针
	}
	else
	{
		SLTNode* tail = *pphead; 
		while (tail->next) 
		{ 
			tail = tail->next; 
		}
		tail->next = newnode;//改变的结构体,用结构体的指针即可
	}
}

//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySListNode(x);
	
	newnode->next = *pphead; 
	*pphead = newnode; 
}


//尾删
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead&&*pphead);//没有节点不需要删除
	//1.一个节点的删除
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else//2.多个节点的删除
	{
		//第一种删除方式
		//SLTNode* prev = NULL; 
		//SLTNode* tail = *pphead; 
		//while (tail->next != NULL)
		//{
		//	prev = tail;
		//	tail = tail->next;
		//}
		//free(tail);
		//tail = NULL;//tail是局部变量,不置空也可以,因为出了作用域tail就销毁了
		//prev->next = NULL;

		//第二种删除方式
		SLTNode* tail = *pphead;
		while (tail->next->next != NULL)
		{
			tail = tail->next; 
		}
		free(tail->next);
		tail->next = NULL; 
	}
}

//头删
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead && *pphead);
	SLTNode* cur = (*pphead)->next; 
	free(*pphead); 
	*pphead = cur; 
}

//打印单链表
void SLTPrint(SLTNode* phead)
{
	while (phead)
	{
		printf("%d->", phead->data);
		phead = phead->next;
	}
	printf("NULL\n");
}

//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{//空链表可以查找
	while (phead)
	{
		if (phead->data == x)
		{
			return phead; 
		}
		phead = phead->next; 
	}
	return NULL;//链表为空找不到
}

// 在pos节点之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	//要么都是空,要么都不是空 --- 当链表不为空时,pos不能为空
	//当链表为空,则pos必须为空
	//总结;pos一定要为有效节点,NULL不是有效节点
	//assert((!pos && !(*pphead)) || (pos && *pphead));

	assert(pos);//pos不为空
	assert(*pphead);//链表不为空
	SLTNode* newnode = BuySListNode(x); 

	if (*pphead == pos)
	{
		//头插
		newnode->next = *pphead;   
		*pphead = newnode;
	}
	else
	{
		SLTNode* prev = *pphead;//用来保存pos前面的那个节点
		while (prev->next != pos) 
		{
			prev = prev->next;
		}
 		prev->next = newnode;
		newnode->next = pos;  
	}
}

// 在pos节点以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuySListNode(x); 
	newnode->next = pos->next; 
	pos->next = newnode;
}

// 删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead);
	assert(pos);
	if (*pphead == pos)
	{
		//头删
		*pphead = pos->next;
		free(pos);
		pos = NULL;
	}
	else
	{
		SLTNode* prev = *pphead;//用来保存pos节点之前的节点地址
		while (prev->next != pos) 
		{
			prev = prev->next; 
		}
		prev->next = pos->next; 
		free(pos); 
		pos = NULL; 
	}
}

// 删除pos的后一个节点
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next);
	SLTNode* cur = pos->next;
	pos->next = cur->next;
	free(cur);
}

//单链表的销毁
void SLTDestroy(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* prev = NULL;
	SLTNode* cur = *pphead;
	while (cur)
	{
		prev = cur;
		cur = cur->next;
		free(prev);
		prev = NULL;
	}
	*pphead = NULL;
	printf("单链表销毁成功\n");
}

5.3 Test.h 文件

#define _CRT_SECURE_NO_WARNINGS 1

#include "SList.h"


void TestSLT1()
{
	SLTNode* plist = NULL; 
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushFront(&plist, 1); 
	SLTPrint(plist);

	SLTNode* pos = SLTFind(plist, 3);//找到3的节点并返回其地址 
	SLTInsert(&plist, pos, 30);//在3前面插入30 
	SLTPrint(plist); 
	 
	SLTInsertAfter(pos, 40);//在3后面插入40 
	SLTPrint(plist); 

	SLTPopBack(&plist);//尾删 
	SLTPrint(plist);  

	SLTPopFront(&plist);//头删 
	SLTPrint(plist); 

	SLTEraseAfter(pos);//删除3后面的那个节点 
	SLTPrint(plist);  

	SLTErase(&plist, pos);//删除节点3 
	SLTPrint(plist); 

	SLTDestroy(&plist);//销毁单链表 
	SLTPrint(plist); 
}

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

在这里插入图片描述


今天的内容就到这里了,后续我会给大家带来一些链表的 oj 题目,大家敬请期待👏

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LCD1602指定位置显示字符串-详细版

本文为博主 日月同辉&#xff0c;与我共生&#xff0c;csdn原创首发。希望看完后能对你有所帮助&#xff0c;不足之处请指正&#xff01;一起交流学习&#xff0c;共同进步&#xff01; > 发布人&#xff1a;日月同辉,与我共生_单片机-CSDN博客 > 欢迎你为独创博主日月同…

工业智能网关:工业物联网智慧连接

工业智能网关是工业互联网的核心设备之一&#xff0c;它承担着连接设备、搜集数据、分析数据、设备控制和实现设备智能化管理的重要任务。随着工业互联网的快速发展&#xff0c;工业智能网关的作用变得越来越重要。 计讯物联5G/4G工业智能网关是一种连接工厂设备与互联网的关键…

考虑区域多能源系统集群协同优化的联合需求侧响应模型(matlab代码)

该程序复现《考虑区域多能源系统集群协同优化的联合需求侧响应模型》文献模型&#xff0c;程序的核心是对多个区域级多能源系统互联系统进行多目标优化&#xff0c;并且考虑联合需求侧响应&#xff0c;以多个区域多能源系统运行总成本最小、碳排放最小为目标&#xff0c;建立多…

腾讯云轻量服务器购买优惠,腾讯云轻量应用服务器优惠购买方法

你是否曾经为如何选择合适的服务器而苦恼&#xff1f;在互联网的海洋中&#xff0c;如何找到一个性价比高&#xff0c;性能稳定&#xff0c;价格合理的服务器供应商&#xff0c;确实是一个让人头疼的问题。今天&#xff0c;我要向你介绍的&#xff0c;是腾讯云轻量应用服务器的…

【问题处理】WPS提示不能启动此对象的源应用程序如何处理?

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 最近在用WPS打开word文件中&#xff0c;插入的Excel附件时&#xff0c;无法打开&#xff0c;提示&#xff1a;“不能启动此对象的源应用程序”。 经过上网查找处理办法&#xff0c;尝试解决&#xff0c;现将解决过程记…

python科研绘图:圆环图

圆环图是一种特殊的图形&#xff0c;它可以显示各个部分与整体之间的关系。圆环图由两个或多个大小不一的饼图叠加而成&#xff0c;中间被挖空&#xff0c;看起来像一个甜甜圈。因此&#xff0c;圆环图也被称为“甜甜圈”图。 与饼图相比&#xff0c;圆环图的空间利用率更高&a…

腾讯云新客户优惠服务器88元/年,540元/3年,另有5年优惠服务器

在选择云服务器时&#xff0c;首先需要考虑的是性能与配置是否与自己的需求相匹配。对于小型网站或者个人博客&#xff0c;轻量应用服务器是一个不错的选择。腾讯云双十一活动中&#xff0c;2核2G轻量应用服务器的活动优惠价为88元/年&#xff0c;2核4G轻量应用服务器的活动优惠…

【软件安装】Centos系统中安装docker容器(华为云HECS云耀服务器)

这篇文章&#xff0c;主要介绍Centos系统中安装docker容器&#xff08;华为云HECS云耀服务器&#xff09;。 目录 一、安装docker 1.1、卸载旧版本docker 1.2、更新repo镜像 1.3、安装依赖包 1.4、添加docker-ce镜像 1.5、安装docker-ce 1.6、查看docker安装版本 1.7、…

深度学习之基于Yolov5的车流或人流量密度统计

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 YOLOv5 DeepSort 车流/人流量密度统计介绍YOLOv5DeepSort车流/人流量密度统计 二、功能三、系统四. 总结 一项目简介 YOLOv5 DeepSort 车流/人流量密度统计…

保驾“双十一” 博睿数据助力电商零售迎高峰无烦忧

如果说“双十一”大战的A面是由天猫、京东、拼多多、唯品会等电商平台&#xff0c;以及一些MCN机构、头部主播拉动的一系列购物狂潮&#xff0c;那么B面则是零售、物流、制造、银行保险等全产业链面对海量流量之下&#xff0c;以强大的心力、脑力与体力应对流量增加和交易陡增的…

1116中信笔试

1116中信笔试 int, Integer的区别&#xff0c;相等如何判断结果Java的异常处理数据库的事务操作Redis的基本数据类型问了HashMap底层实现TCP协议MySQL的隔离级别创建线程的几种方式双亲委派机制 &#xff0c;它的优点linux命令&#xff08;查看线程&#xff09; java和数据库ha…

【云原生-Kurbernets篇】Kurbernets集群的调度策略

调度 一、Kurbernetes的list-watch机制1.1 list-watch机制简介1.2 创建pod的流程&#xff08;结合list-watch机制&#xff09; 二、Scheduler的调度策略2.1 简介2.2 预选策略&#xff08;predicate&#xff09;2.3 优选策略&#xff08;priorities&#xff09; 三、标签管理3.1…

【C语言 | 指针】指针和数关系——剪不断,理还乱

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

云ES高级监控告警

一、高级监控告警配置 1.1 操作入口 1.2 配置告警模块 1.2.1 新建联系人 添加联系人后,需要进行激活 1.2.2 新建联系人组 1.2.3 创建报警组 1.2.4 新建报警规则

超市管理系统

闲着无聊写了个超市管理系统&#xff0c;包括商品管理、进销存、角色权限管理&#xff0c;很不错的项目分享给大家 1 商品管理 1.1 分类管理 分类信息主要包括名称、描述&#xff0c;可以进行停用、启用 1.2 商品信息 1.3 积分商品 1.4 销售统计 2 库存管理 2.1 仓库管理…

YOLOv5项目实战(3)— 如何批量命名数据集中的图片

前言:Hello大家好,我是小哥谈。本节课就教大家如何去批量命名数据集中的图片,希望大家学习之后可以有所收获!~🌈 前期回顾: YOLOv5项目实战(1)— 如何去训练模型 YOLOv5项目实战(2࿰

【AI视野·今日Robot 机器人论文速览 第六十五期】Mon, 30 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Mon, 30 Oct 2023 Totally 18 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Gen2Sim: Scaling up Robot Learning in Simulation with Generative Models Authors Pushkal Katara, Zhou Xian, Katerina F…

9.程序的机器级代码表示,CISC和RISC

目录 一. x86汇遍语言基础&#xff08;Intel格式&#xff09; 二. AT&T格式汇编语言 三. 程序的机器级代码表示 &#xff08;1&#xff09;选择语句 &#xff08;2&#xff09;循环语句 &#xff08;3&#xff09;函数调用 1.函数调用命令 2.栈帧及其访问 3.栈帧的…

Backblaze 2023 Q3硬盘故障质量报告解读

作为一家在2021年在美国纳斯达克上市的云端备份公司&#xff0c;Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告&#xff0c;给大家提供了一份真实应用场景下的稳定性分析参考数据。2023年度之前发布的两次报告&#xff0c;请参考&#xff1a; Backblaze发布2…

为什么LDO一般不用在大电流场景?

首先了解一下LDO是什么&#xff1f; LDO&#xff08;low dropout regulator&#xff0c;低压差线性稳压器&#xff09;或者低压降稳压器&#xff0c;它的典型特性就是压降。 那么什么是压降&#xff1f; 压降电压 VDO 是指为实现正常稳压&#xff0c;输入电压 VIN 必须高出 所…