前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >链表基础知识(二、双向链表头插、尾插、头删、尾删、查找、删除、插入)

链表基础知识(二、双向链表头插、尾插、头删、尾删、查找、删除、插入)

作者头像
走在努力路上的自己
发布于 2024-01-26 08:53:05
发布于 2024-01-26 08:53:05
1.6K00
代码可运行
举报
运行总次数:0
代码可运行

一、双向链表的概念

双向链表,即一个节点中有两个指针域,一个存放当前节点前一个节点的地址,另一个存放当前节点后一个节点的地址。

(STL中list就是这个结构)

双链表的节点:

二、 双向链表的优缺点分析​与对比

2.1双向链表特点:

1.每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 实现起来要困难一些   2.相对于单向链表, 必然占用内存空间更大一些.   3.既可以从头遍历到尾, 又可以从尾遍历到头

2.2双链表的优劣:

2.3循环链表的优劣

循环表的好处主要包括以下几点:

  • 灵活性:循环链表可以从任何一个节点开始遍历,而且任何节点都可以作为头节点。这种灵活性使得循环链表在处理某些问题时比其他类型的链表更有优势。
  • 简化操作:在循环链表中,插入和删除操作相对简便,不需要对头尾节点
  • 行特殊处理。这种简便性可以提高算法的效率,降低编程的复杂性。
  • 适用于循环问题:循环链表可以实现循环访问,因此特别适用于解决涉及到循环问题的场景。
  • 便于实现队列数据结构:使用循环链表来实现队列数据结构可以简化操作,只需要维护一个尾节点指针即可,因为尾节点的后向节点就是队头节点。
  • 方便操作系统管理和应用程序运行:循环链表在操作系统和应用程序中也有广泛的应用。例如,操作系统可以利用循环链表来管理多个应用程序,通过循环遍历来给每个应用程序分配执行时间。
  • 可用于实现高级数据结构:循环双向链表可以用于实现高级数据结构,例如斐波那契堆(Fibonacci Heap),从而扩展了其在复杂算法和数据结构中的应用范围。

循环链表的缺点主要包括:

  • 内存占用更多:相比单链表,循环链表需要更多的内存空间来存储链接信息。这是因为循环链表中的每个节点都需要指向下一个节点,形成一个闭环,从而增加了内存开销。
  • 代码复杂度提高:循环链表的代码实现相比单链表要复杂一些。在插入、删除节点或遍历链表时,需要特别注意处理边界条件和循环结构,这可能会增加开发和调试的难度。
  • 潜在的死循环风险:如果循环链表中的链接关系出现错误,可能会导致死循环的情况发生。例如,在插入或删除节点时,如果没有正确更新链接关系,就可能导致链表无法正确遍历或陷入无限循环中。

2.4 顺序表和链表的优缺点分析​

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

结构复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。

3.1SList.c

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once
#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>


typedef int LTDataType;
//带哨兵位的头节点,第一个节点不存储有效数据,不能存储链表的长度
//typedef char LTDataType;
//typedef double LTDataType;无法存储链表长度


//Slist  双向链表
//DList  单链表
typedef struct ListNode
{
	struct ListNode* next;
	struct ListNode* prev;
	LTDataType data;
}ListNode;

ListNode* ListInit();
void ListDestory(ListNode* phead);
void ListPrint(ListNode* phead);

void ListPushBack(ListNode* phead, LTDataType x);
void ListPushFront(ListNode* phead, LTDataType x);
void ListPopFront(ListNode* phead);
void ListPopBack(ListNode* phead);

ListNode* ListFind(ListNode* phead, LTDataType x);
// pos位置之前插入x
void ListInsert(ListNode* pos, LTDataType x);
// 删除pos位置的值
void ListErase(ListNode* pos);

//bool ListEmpty(ListNode* phead);
//int ListSize(ListNode* phead);//链表的长度

3.2创建一个新节点、头节点

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ListNode* BuyListNode(LTDataType x)
//创建一个新节点
{
	ListNode* newnode = malloc(sizeof(ListNode));
	//malloc分配大小,是一个ListNode结构体的大小
	newnode->data = x;//将新节点的data字段设置为参数x的值
	newnode->next = NULL;//给新节点的next存储的地址置空
	newnode->prev = NULL;//给新节点的prev存储的地址置空

	return newnode;
}
ListNode* ListInit()
//创建头节点
{
	ListNode* phead = BuyListNode(0);//phead指向了这个新创建的节点
	phead->next = phead; // 将phead的 next 指向其自身
	phead->prev = phead; // 将phead的 prev 指向其自身

	return phead;//返回phead,即头节点
}

3.3头插

在头节点后插入

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ListPushFront(ListNode* phead, LTDataType x)
{
	assert(phead);//此节点不为空

	//顺序不能换
	ListNode* newnode = BuyListNode(x);
	newnode->next = phead->next;//存储phead的next,即下一个节点
	phead->next->prev = newnode;//下一个节点的prev指向newnode

	phead->next = newnode;//下一个节点的next 指向 newnode
	newnode->prev = phead;//newnode的prev 指向 phead
}

3.4尾插

在头节点前插入

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ListPushBack(ListNode* phead, LTDataType x)
//x = 0,尾插
{
	assert(phead);//phead不为空
	ListNode* tail = phead->prev;//tail存储phead的prev中的地址,即最后一个节点
	ListNode* newnode = BuyListNode(x);//创建一个新节点
	
	tail->next = newnode;//上一个节点的next指向新节点
	newnode->prev = tail;//新节点的prev指向phead
	newnode->next = phead;//新节点的next指向phead
	phead->prev = newnode;//上一个节点的prev指向新节点
}

3.5头删

在头结点后删除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ListPopFront(ListNode* phead)
{
	assert(phead);//phead不为空
	assert(phead->next != phead);

	ListNode* first = phead->next;//先first存储phead的next中的地址,即phead的下一个节点
	ListNode* second = first->next;//再second存储下一个的节点的next中的地址,即下下个节点
	phead->next = second;//phead的next指向下下一个节点
	second->prev = phead;//下下一个节点的prev指向phead

	free(first);//下一个节点的空间被释放
	first = NULL;//first置空
}

3.6尾删

在头节点前删除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ListPopBack(ListNode* phead)
{
	assert(phead);//此节点不为空
	assert(phead->next != phead);

	ListNode* tail = phead->prev;//先tail存储phead的prev中的地址,即上一个节点
	ListNode* prev = tail->prev;//prev存储上一个节点的prev中的地址,即上上一个节点

	prev->next = phead;//上上个节点的next指向phead
	phead->prev = prev;//phead的prev指向上上个节点

	free(tail);//释放tail存储的空间,即上个节点的空间
	tail = NULL;//tail置空
	
}

3.7查找

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ListNode* ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);//此节点不为空
	ListNode* cur = phead->next;//cur存储phead的next中的地址,即下一个节点
	while (cur != phead)//不是头节点
	{
		if (cur->data == x)//如果是要查找的地址
		{
			return cur;//找到了返回这个地址
		}

		cur = cur->next;//指向下一个节点
	}

	return NULL;//没有找到,返回空
}

3.8删除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 删除pos位置的值
void ListErase(ListNode* pos)
{
	assert(pos);//此节点不为空

	ListNode* prev = pos->prev;//prev存储pos的prev中的地址,即上一个节点
	ListNode* next = pos->next;//next存储pos的next中的地址,即下一个节点
	prev->next = next;//上一个节点的next指向pos的next,即下一个节点
	next->prev = prev;//下一个节点的prev指向pos的prev,即上一个节点
	free(pos);//释放pos所在的空间
}

3.9插入

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// pos位置之前插入x
void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);//此节点不为空
	ListNode* prev = pos->prev;//prev存储pos的prev中的地址,即pos上一个节点
	ListNode* newnode = BuyListNode(x);//创建一个新节点

	// prev newnode pos
	prev->next = newnode;//上一个节点的next指向newnode
	newnode->prev = prev;//新节点的prev指向上一个节点
	newnode->next = pos;//新节点的next指向pos
	pos->prev = newnode;//pos的prev指向newnode
}

3.10查找

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ListNode* ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);//此节点不为空
	ListNode* cur = phead->next;//cur存储phead的next中的地址,即下一个节点
	while (cur != phead)//不是头节点
	{
		if (cur->data == x)//如果是要查找的地址
		{
			return cur;//找到了返回这个地址
		}

		cur = cur->next;//指向下一个节点
	}

	return NULL;//没有找到,返回空
}

3.11打印链表

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ListPrint(ListNode* phead)
{
	assert(phead);//此节点不为空

	ListNode* cur = phead->next;//cur存储phead的next中的地址,即下一个节点
	while (cur != phead)//cur不是指向的自己(头节点)
	{								
		printf("%d ", cur->data);
		//打印cur存储的数据,即下一个地址的数据(因为有头节点)
		cur = cur->next;//指向下一个节点
	}
	printf("\n");
}

3.12销毁链表

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ListDestory(ListNode* phead)
{
	assert(phead);//phead不为空
	ListNode* cur = phead->next;//cur存储phead的next中的地址,即下一个节点
	while (cur != phead)//cur指向的不是自己
	{
		ListNode* next = cur->next;//next指向下一个节点
		free(cur);//释放cur所在的空间
		cur = next;//cur指向下一个节点
	}

	free(phead);//释放头节点所在的空间
	phead = NULL;//头节点置空

}

四、简化链表,用插入和删除代替其他插入删除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ListPushBack(ListNode* phead, LTDataType x)
{
	assert(phead);//phead不为空
	ListInsert(phead, x);//可以用插入来表示尾插
}

void ListPushFront(ListNode* phead, LTDataType x)
{
	assert(phead);//此节点不为空
	ListInsert(phead->next, x);//可以用插入来表示头插
}

void ListPopFront(ListNode* phead)
{
	assert(phead);//phead不为空
	ListErase(phead->next);//可以用删除表示头删
}

void ListPopBack(ListNode* phead)
{
	assert(phead);//此节点不为空
	ListErase(phead->prev);//可以用删除表示尾删
}

// pos位置之前插入x
void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);//此节点不为空
	ListNode* prev = pos->prev;//prev存储pos的prev中的地址,即pos上一个节点
	ListNode* newnode = BuyListNode(x);//创建一个新节点

	// prev newnode pos
	prev->next = newnode;//上一个节点的next指向newnode
	newnode->prev = prev;//新节点的prev指向上一个节点
	newnode->next = pos;//新节点的next指向pos
	pos->prev = newnode;//pos的prev指向newnode
}

// 删除pos位置的值
void ListErase(ListNode* pos)
{
	assert(pos);//此节点不为空

	ListNode* prev = pos->prev;//prev存储pos的prev中的地址,即上一个节点
	ListNode* next = pos->next;//next存储pos的next中的地址,即下一个节点
	prev->next = next;//上一个节点的next指向pos的next,即下一个节点
	next->prev = prev;//下一个节点的prev指向pos的prev,即上一个节点
	free(pos);//释放pos所在的空间
}

五、SList.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include"List.h"

ListNode* BuyListNode(LTDataType x)
//创建一个新节点
{
	ListNode* newnode = malloc(sizeof(ListNode));
	//malloc分配大小,是一个ListNode结构体的大小
	newnode->data = x;//将新节点的data字段设置为参数x的值
	newnode->next = NULL;//给新节点的next存储的地址置空
	newnode->prev = NULL;//给新节点的prev存储的地址置空

	return newnode;
}

//void ListInit(ListNode* phead)
初始化了链表的新节点
//{
//	phead = BuyListNode(0);//phead指向了这个新创建的节点
//	phead->next = phead;//将phead的 next 指向其自身
//	phead->prev = phead;//将phead的 prev 指向其自身
//}

ListNode* ListInit()
//创建头节点
{
	ListNode* phead = BuyListNode(0);//phead指向了这个新创建的节点
	phead->next = phead; // 将phead的 next 指向其自身
	phead->prev = phead; // 将phead的 prev 指向其自身

	return phead;//返回phead,即头节点
}


void ListDestory(ListNode* phead)
{
	assert(phead);//phead不为空
	ListNode* cur = phead->next;//cur存储phead的next中的地址,即下一个节点
	while (cur != phead)//cur指向的不是自己
	{
		ListNode* next = cur->next;//next指向下一个节点
		free(cur);//释放cur所在的空间
		cur = next;//cur指向下一个节点
	}

	free(phead);//释放头节点所在的空间
	phead = NULL;//头节点置空

}

void ListPrint(ListNode* phead)
{
	assert(phead);//此节点不为空

	ListNode* cur = phead->next;//cur存储phead的next中的地址,即下一个节点
	while (cur != phead)//cur不是指向的自己(头节点)
	{								
		printf("%d ", cur->data);
		//打印cur存储的数据,即下一个地址的数据(因为有头节点)
		cur = cur->next;//指向下一个节点
	}
	printf("\n");
}


void ListPushBack(ListNode* phead, LTDataType x)
//x = 0,尾插
{
	//assert(phead);//phead不为空
	//ListNode* tail = phead->prev;//tail存储phead的prev中的地址,即最后一个节点
	//ListNode* newnode = BuyListNode(x);//创建一个新节点
	//
	//tail->next = newnode;//上一个节点的next指向新节点
	//newnode->prev = tail;//新节点的prev指向phead
	//newnode->next = phead;//新节点的next指向phead
	//phead->prev = newnode;//上一个节点的prev指向新节点
	ListInsert(phead, x);//可以用插入来表示尾插
}



//void ListPushFront(ListNode* phead, LTDataType x)
x = 0,头插
//{
//	assert(phead);//此节点不为空
//
//	ListNode* first = phead->next;//first存储phead的next中的地址,即下一个节点
//	ListNode* newnode = BuyListNode(x);//在x处创建一个新节点
//
//	// phead newnode first
//	phead->next = newnode;//下一个节点的next指向新节点
//	newnode->prev = phead;//新节点的prev指向此节点
//	newnode->next = first;//新节点的next指向此节点
//	first->prev = newnode;//下一个节点的prev指向新节点
//}

void ListPushFront(ListNode* phead, LTDataType x)
{
	assert(phead);//此节点不为空

	//顺序不能换
	ListNode* newnode = BuyListNode(x);
	newnode->next = phead->next;//存储phead的next,即下一个节点
	phead->next->prev = newnode;//下一个节点的prev指向newnode

	phead->next = newnode;//下一个节点的next 指向 newnode
	newnode->prev = phead;//newnode的prev 指向 phead
	//ListInsert(phead->next, x);//可以用插入来表示头插
}

void ListPopFront(ListNode* phead)
{
	assert(phead);//phead不为空
	assert(phead->next != phead);

	ListNode* first = phead->next;//先first存储phead的next中的地址,即phead的下一个节点
	ListNode* second = first->next;//再second存储下一个的节点的next中的地址,即下下个节点
	phead->next = second;//phead的next指向下下一个节点
	second->prev = phead;//下下一个节点的prev指向phead

	free(first);//下一个节点的空间被释放
	first = NULL;//first置空

	//ListErase(phead->next);//可以用删除表示头删
}

void ListPopBack(ListNode* phead)
{
	assert(phead);//此节点不为空
	/*assert(phead->next != phead);

	ListNode* tail = phead->prev;//先tail存储phead的prev中的地址,即上一个节点
	ListNode* prev = tail->prev;//prev存储上一个节点的prev中的地址,即上上一个节点

	prev->next = phead;//上上个节点的next指向phead
	phead->prev = prev;//phead的prev指向上上个节点

	free(tail);//释放tail存储的空间,即上个节点的空间
	tail = NULL;//tail置空
	*/

	ListErase(phead->prev);//可以用删除表示尾删
}

ListNode* ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);//此节点不为空
	ListNode* cur = phead->next;//cur存储phead的next中的地址,即下一个节点
	while (cur != phead)//不是头节点
	{
		if (cur->data == x)//如果是要查找的地址
		{
			return cur;//找到了返回这个地址
		}

		cur = cur->next;//指向下一个节点
	}

	return NULL;//没有找到,返回空
}

// pos位置之前插入x
void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);//此节点不为空
	ListNode* prev = pos->prev;//prev存储pos的prev中的地址,即pos上一个节点
	ListNode* newnode = BuyListNode(x);//创建一个新节点

	// prev newnode pos
	prev->next = newnode;//上一个节点的next指向newnode
	newnode->prev = prev;//新节点的prev指向上一个节点
	newnode->next = pos;//新节点的next指向pos
	pos->prev = newnode;//pos的prev指向newnode
}

// 删除pos位置的值
void ListErase(ListNode* pos)
{
	assert(pos);//此节点不为空

	ListNode* prev = pos->prev;//prev存储pos的prev中的地址,即上一个节点
	ListNode* next = pos->next;//next存储pos的next中的地址,即下一个节点
	prev->next = next;//上一个节点的next指向pos的next,即下一个节点
	next->prev = prev;//下一个节点的prev指向pos的prev,即上一个节点
	free(pos);//释放pos所在的空间
}

六、Test.c

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include"List.h"

void TestList1()
{
	ListNode* plist = ListInit();//plist为头节点
	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPushBack(plist, 4);
	ListPrint(plist);

	ListPushFront(plist, 0);
	ListPushBack(plist, -1);
	ListPrint(plist);

	/*ListPopFront(plist);
	ListPopFront(plist);
	ListPopFront(plist);
	ListPrint(plist);

	ListPopBack(plist);
	ListPrint(plist);

	ListDestory(plist);*/

}

int main()
{
	TestList1();

	return 0;
}

今天就先到这了!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
个人网盘分享·Alist的安装配置和使用
对我来说,它可以让我基于自己的服务器自由的分享自己的文件给亲人或者朋友,而不是依赖第三方平台,但是它强大也强大在可以依赖各个云盘实现共享而不占用自己服务器,官方支持的云盘如下:
我不是程序员110
2022/10/28
25.6K1
个人网盘分享·Alist的安装配置和使用
挂在网盘到本地磁盘(以中移动云盘为例)
按上图信息填写内容,其中:地址后面有一个复选框不选择,用户名密码来自Alist设置-后端的菜单页面。
Criss@陈磊
2023/09/18
1.7K0
挂在网盘到本地磁盘(以中移动云盘为例)
【说站】Alist+RaiDrive,一招教你硬盘多出80个T!
这是小高电脑磁盘分区的截图,细心的朋友可能会发现:哎!小高的电脑怎么还有一块容量将近8T的分区?
很酷的站长
2022/11/25
5.4K1
【说站】Alist+RaiDrive,一招教你硬盘多出80个T!
自建Alist共享网盘网站
一、背景 由于百度网盘下载限速,所以就用了天翼云,坚果云,阿里云等,结果每次都要登录,就很拉跨, 所以在这里部署一套共享alist网盘,实现随时随地,只要有网,开箱即用。 二、docker部署 官方地址 1.安装 # 端口自定义即可 docker run -d --restart=always -v /etc/alist:/opt/alist/data -p 5244:5244 --name="alist" xhofe/alist:latest 2.密码化密码 docker exec -it alis
懿曲折扇情
2022/09/06
3.4K0
自建Alist共享网盘网站
27.3K Star开源一个支持多种存储的项目,支持各种云盘,功能强大
开源日记
2023/08/10
5260
27.3K Star开源一个支持多种存储的项目,支持各种云盘,功能强大
共享OneDrive、Drive、百度等不同云盘数据:MultCloud
  本文介绍通过MultCloud平台,在国内实现谷歌Drive、OneDrive、百度网盘等不同云盘之间数据的传输、共享等操作的免费方法。
疯狂学习GIS
2024/01/10
4940
共享OneDrive、Drive、百度等不同云盘数据:MultCloud
云盘行业的“冰与火”
无论是在日常生活还是在漫漫旅途中,人们越来越习惯打开手机摄像头,定格记录下美好瞬间;遇见喜爱的剧集时,也愿意将之保存下来。不过,若想将这些图片、视频资料全部保存下来的话,仅仅依靠手机的存储空间是远远不够的。另外,为了防止误删文件资料,云端备份也逐渐成为了人们的基本操作。在此背景下,无须携带、存储空间更大的云盘产品就成为了备受人们青睐的存储工具。
刘旷
2022/11/03
6990
苹果Files接入的这个产品,堪称百度AI战略的前瞻布局?
2005年,史蒂夫•乔布斯(Steve Jobs)在D3数字大会上给出了一个设想:操作系统能不能不带文件系统?他的理由是,不论是电子邮件还是iTunes还是照片,这些应用都可以让用户很好地管理和找到对应的文件,系统层面的文件管理应该透明,不需要用户去使用。在iOS上,乔布斯这一设想得到了实现,iOS一直没有文件管理系统,不同文件只能在对应的App中才能被打开。 不过,前几天的WWDC 2017年却改变了这一点:苹果宣布iOS11将内置Files文件管理器,这就跟MacOS的Finder一样,可以对文件进行管
罗超频道
2018/04/16
1.6K0
苹果Files接入的这个产品,堪称百度AI战略的前瞻布局?
中国移动“捣腾”移动云盘,是一门好生意吗?
今年以来,中国移动对移动云盘这个存在已久的产品(前身是和彩云)开始重视起来,无论是内部的资源配给,还是外部的营销推广,移动云盘隐然已成为中国移动最重要的ToC产品之一。
悲了伤的白犀牛
2022/12/14
1.1K0
个人云服务的搭建(白嫖)之旅
WebDAV ,全称是Web-based Distributed Authoring and Versioning,维基百科上对它的解释是这样的:基于Web的分布式编写和版本控制(WebDAV)是超文本传输协议(HTTP)的扩展,有利于用户间协同编辑和管理存储在万维网服务器文档。
不愿意做鱼的小鲸鱼
2022/09/26
6.8K0
个人云服务的搭建(白嫖)之旅
360云盘退役,百度网盘和天翼云上演饥饿游戏
“冬天来了,春天还会远吗?”这句话,可以总结刚刚发生的360云盘关停事件。 每天都有互联网业务出现,也会有互联网业务消失。昨天,360云盘发布公告表示将停止个人云盘服务,在网络存储、传播内容的合法性和安全性得到彻底解决之前不再考虑恢复,之后将转型企业云服务,这一事件被一些媒体解读为“云盘时代”结束。在此之前,新浪微盘、金山快盘、UC 网盘、华为网盘早已关闭。 曾经排名前十的网盘大部分都已退场,现在仅有百度网盘、天翼云和微云三大玩家。昨天还有消息称百度网盘也将终止服务,旋即被百度官方辟谣。然而,个人云存储市
罗超频道
2018/04/27
3.5K0
360云盘退役,百度网盘和天翼云上演饥饿游戏
为什么说AI将是下一代网盘的基石?
你可能用过iPhone自带相册的“回忆”功能:系统将同一地方或相关主题的照片精选后,再自动配上BGM生成小视频。虽然结果有些“粗糙”,却改变了我们使用照片的方式。 iPhone相册的“回忆”功能,是AI加持下手机相册服务主动化的一次尝试。而在云端网盘上,利用更强大的云端AI技术,照片的智能化服务已向前一步。前段时间,小红书、微博等平台有很多用户分享了#如果回忆会说话#照片回忆杀,照片上的文案不是手工输入而是AI配置。 这是百度网盘做的一个活动,用户上传任意类型的图片到百度网盘,AI都会结合照片上的人物、
罗超频道
2022/08/26
1.7K0
为什么说AI将是下一代网盘的基石?
【AList】摆脱数据绑架,实现私人网盘自由-网盘搭建及进阶
许多朋友都有使用过网盘,像比较大的百度网盘、天翼云盘以及新用户就送2T的123盘,但是也有不少刚需注重隐私的朋友搭建私有网盘,这就需要用到一些网盘系统,像nextcloud就是其中一种。有用过的网友就知道,webdav协议的网盘可以直接挂载到windows系统,当成文件目录使用,我感觉用起来很方便。
羽翼博客
2023/01/31
5.2K0
Alist宝塔部署及其美化
在过去,我的Alist一直作为本地服务运行,它承载着我托管各种杂七杂八的网盘的重任,比如收集文件用的坚果云,存放资源的蓝奏云,放课程视频的百度云。最近我才意识到,这个好像可以在服务器上部署!因此,我决定将我的Alist部署到服务器上,这不仅提升了访问的便捷性,也让我的服务更加稳定可靠,我也会在上面分享一些我的代码文件,但是因为带宽原因,我不会放大于10MB的文件,防止给大家带来不好的体验。
柳神
2024/06/05
1.2K0
Alist宝塔部署及其美化
给你的NAS无限可能,安装小晓雅全家桶影音库
家庭存储和娱乐的需求日益增长。无论是高清电影、电视剧,还是音乐和照片,我们都希望有一个稳定且高效的系统来管理和享受这些资源。而网络附加存储(NAS)作为家庭数据中心的核心,其功能的强大与否直接决定了我们的体验。
星哥玩云
2024/08/28
2000
给你的NAS无限可能,安装小晓雅全家桶影音库
如何在Windows部署Alist全平台网盘神器并结合内网穿透实现公网访问本地网盘
AList 是一个支持多种存储,支持网页浏览和 WebDAV的文件列表程序,可以实现多种网盘挂载为硬盘,并可以挂载不限量的网络资源。或者说是一个网盘聚合器,可以将你的网盘挂载到一起,方便统一管理,简单的说 通过本地浏览器管理多种网盘的程序,重点是免费!
aosei
2024/03/22
3K0
如何在Windows部署Alist全平台网盘神器并结合内网穿透实现公网访问本地网盘
懒人福音!CasaOS设备上轻松部署小雅AList,内网穿透远程观影不是梦!
本文主要介绍如何在安装了轻NAS系统CasaOS的小主机中部署小雅AList,并使用AList挂载小雅alist,结合cpolar内网穿透工具轻松实现远程访问小雅中的海量资源。无需公网IP,也不用设置路由器那么麻烦。
E绵绵
2024/11/15
1.4K0
懒人福音!CasaOS设备上轻松部署小雅AList,内网穿透远程观影不是梦!
【教程】宝塔面板安装 AList (非一键安装)
经历了 2016 年的云盘关停潮之后,百度网盘和腾讯微云成为互联网企业中的行业代表,现在阿里也带来了两款云盘产品,分别是阿里云盘和 Teambition,今天我们要说的是前者,之前很多用过OneDrive列表程序风靡一段时间后因不稳定等原因被纷纷抛弃了,听闻也从阵营中换到了Fast大家庭,直到现在阿里推出的云盘,也好刚好Xhofe大佬开发了一个列表程序,今天我们就来讲一下如何在宝塔面板上搭建吧!
听闻所见
2023/08/02
3.4K0
拒绝充钱提速,快来搭建自己的网络云盘吧!!
说起百度网盘,想必大家都对那蜗牛般的下载速度咬牙切齿 o(≧口≦)o,每次看到那一百出头的下载速度,我就想着如果我自己有自己的网盘就好了,安心又快速!
永恒君
2022/12/06
1.6K0
拒绝充钱提速,快来搭建自己的网络云盘吧!!
告别“限速”,个人网盘进入云时代
在数字经济广泛渗透的条件下,个人网盘市场也得到了长足发展。而在5G和AI的加持下,个人网盘不断进行技术融合和迭代,云盘已然成为互联网用户以及智能设备存储的基本服务,而其应用场景也顺理成章地开始向各个细分领域拓展。
刘旷
2022/12/27
2K0
推荐阅读
相关推荐
个人网盘分享·Alist的安装配置和使用
更多 >
LV.5
这个人很懒,什么都没有留下~
目录
  • 一、双向链表的概念
  • 二、 双向链表的优缺点分析​与对比
    • 2.1双向链表特点:
    • 2.2双链表的优劣:
    • 2.3循环链表的优劣
    • 2.4 顺序表和链表的优缺点分析​
  • 三、带头双向循环链表增删改查实现
    • 3.1SList.c
    • 3.2创建一个新节点、头节点
    • 3.3头插
    • 3.4尾插
    • 3.5头删
    • 3.6尾删
    • 3.7查找
    • 3.8删除
    • 3.9插入
    • 3.10查找
    • 3.11打印链表
    • 3.12销毁链表
  • 四、简化链表,用插入和删除代替其他插入删除
  • 五、SList.h
  • 六、Test.c
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档