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

目录

一、双向链表的概念

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

 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


书接上文:

链表基础知识(一、单链表、头插、尾插、头删、尾删、查找、删除、插入)-CSDN博客

一、双向链表的概念

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

(STL中list就是这个结构)

双链表的节点:

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

 2.1双向链表特点:

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

2.2双链表的优劣:

2.3循环链表的优劣

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

  • 灵活性:循环链表可以从任何一个节点开始遍历,而且任何节点都可以作为头节点。这种灵活性使得循环链表在处理某些问题时比其他类型的链表更有优势。

  • 简化操作:在循环链表中,插入和删除操作相对简便,不需要对头尾节点

  • 行特殊处理。这种简便性可以提高算法的效率,降低编程的复杂性。

  • 适用于循环问题:循环链表可以实现循环访问,因此特别适用于解决涉及到循环问题的场景。

  • 便于实现队列数据结构:使用循环链表来实现队列数据结构可以简化操作,只需要维护一个尾节点指针即可,因为尾节点的后向节点就是队头节点。

  • 方便操作系统管理和应用程序运行:循环链表在操作系统和应用程序中也有广泛的应用。例如,操作系统可以利用循环链表来管理多个应用程序,通过循环遍历来给每个应用程序分配执行时间。

  • 可用于实现高级数据结构:循环双向链表可以用于实现高级数据结构,例如斐波那契堆(Fibonacci Heap),从而扩展了其在复杂算法和数据结构中的应用范围。

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

  • 内存占用更多:相比单链表,循环链表需要更多的内存空间来存储链接信息。这是因为循环链表中的每个节点都需要指向下一个节点,形成一个闭环,从而增加了内存开销。

  • 代码复杂度提高:循环链表的代码实现相比单链表要复杂一些。在插入、删除节点或遍历链表时,需要特别注意处理边界条件和循环结构,这可能会增加开发和调试的难度。

  • 潜在的死循环风险:如果循环链表中的链接关系出现错误,可能会导致死循环的情况发生。例如,在插入或删除节点时,如果没有正确更新链接关系,就可能导致链表无法正确遍历或陷入无限循环中。

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

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

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

3.1SList.c

#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创建一个新节点、头节点

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头插

在头节点后插入

void ListPushFront(ListNode* phead, LTDataType x)
{assert(phead);//此节点不为空//顺序不能换ListNode* newnode = BuyListNode(x);newnode->next = phead->next;//存储phead的next,即下一个节点phead->next->prev = newnode;//下一个节点的prev指向newnodephead->next = newnode;//下一个节点的next 指向 newnodenewnode->prev = phead;//newnode的prev 指向 phead
}

3.4尾插

在头节点前插入

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指向pheadnewnode->next = phead;//新节点的next指向pheadphead->prev = newnode;//上一个节点的prev指向新节点
}

3.5头删

在头结点后删除

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指向pheadfree(first);//下一个节点的空间被释放first = NULL;//first置空
}

3.6尾删

在头节点前删除

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指向pheadphead->prev = prev;//phead的prev指向上上个节点free(tail);//释放tail存储的空间,即上个节点的空间tail = NULL;//tail置空}

3.7查找

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删除

// 删除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插入

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

3.10查找

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打印链表

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销毁链表

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 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 posprev->next = newnode;//上一个节点的next指向newnodenewnode->prev = prev;//新节点的prev指向上一个节点newnode->next = pos;//新节点的next指向pospos->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

#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指向newnodephead->next = newnode;//下一个节点的next 指向 newnodenewnode->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指向pheadfree(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指向pheadphead->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 posprev->next = newnode;//上一个节点的next指向newnodenewnode->prev = prev;//新节点的prev指向上一个节点newnode->next = pos;//新节点的next指向pospos->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

#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;
}

今天就先到这了!!!

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

成为软件测试工程师需要学什么?

成为软件测试工程师需要学习测试环境的搭建、前端开发知识、数据库知识、测试理论基础、开发语言基础、自动化测试、进阶内容。 1、测试环境的搭建 本部分主要是学习从操作系统开始&#xff0c;有关的计算机基础知识、软件和硬件知识、计算机理论知识、网络知识、如何在一个操…

C/C++ 表达式求值(含多位数)

个人主页&#xff1a;仍有未知等待探索_C语言疑难,数据结构,算法-CSDN博客 专题分栏&#xff1a;算法_仍有未知等待探索的博客-CSDN博客 目录 一、前言 二、解析 分析 最后直接上代码&#xff01; 一、前言 表达式求值是一个比较基础的代码关于栈的使用。在写的时候充分锻炼…

WPF——命令commond的实现方法

命令commond的实现方法 属性通知的方式 鼠标监听绑定事件 行为&#xff1a;可以传递界面控件的参数 第一种&#xff1a; 第二种&#xff1a; 附加属性 propa&#xff1a;附加属性快捷方式

【谭浩强C语言:前八章编程题(多解)】

文章目录 第一章1. 求两个整数之和(p7) 第二章2. 求三个数中的较大值&#xff08;用函数&#xff09;(p14、p107)3.求123...n(求n的阶乘&#xff0c;用for循环与while循环)(P17)1.循环求n的阶乘2.递归求n的阶乘(n< 10) 4.有M个学生&#xff0c;输出成绩在80分以上的学生的学…

【C++】封装:练习案例-点和圆的关系

练习案例&#xff1a;点和圆的关系 设计一个圆形类&#xff08;Circle&#xff09;&#xff0c;和一个点类&#xff08;Point&#xff09;&#xff0c;计算点和圆的关系。 思路&#xff1a; 1&#xff09;创建点类point.h和point.cpp 2&#xff09;创建圆类circle.h和circle…

pytorch实现DCP暗通道先验去雾算法及其onnx导出

pytorch实现DCP暗通道先验去雾算法及其onnx导出 简介实现ONNX导出导出测试 简介 最近在做图像去雾&#xff0c;于是在Pytorch上复现了一下dcp算法。暗通道先验去雾算法是大神何恺明2009年发表在CVPR上的一篇论文&#xff0c;还获得了当年的CVPR最佳论文。 实现 具体原理就不…

【贪心算法】【中位贪心】LeetCode:100123.执行操作使频率分数最大

涉及知识点 双指针 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 贪心算法 题目 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 你可以对数组执行 至多 k 次操作&#xff1a; 从数组中选择一个下标 i &#xff0c;将 nums[i] …

网络编程day2作业

1.tcp实现通信 服务器&#xff1a; //tcp服务端#include <head.h>#define SERPORT 8888 #define IP "192.168.125.6"int main(int argc, const char *argv[]) { //1.创建套接字int sfdsocket(AF_INET,SOCK_STREAM,0);//2.绑定struct sockaddr_in ser;ser.sin…

喜报丨迪捷软件入选2023年浙江省信息技术应用创新典型案例

12月6日&#xff0c;浙江省经信厅公示了2023年浙江省信息技术应用创新典型案例入围名单。本次案例征集活动&#xff0c;由浙江省经信厅、省密码管理局、工业和信息化部网络安全产业发展中心联合组织开展&#xff0c;共遴选出24个优秀典型解决方案&#xff0c;迪捷软件“基于全数…

LeetCode刷题--- 找出所有子集的异或总和再求和

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递归递归、搜…

互联网加竞赛 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

猫头虎博主揭秘:令人叹为观止的编程语言与代码技巧 ‍

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

python如何发送企业微信群消息

一、创建机器人&#xff0c;并获取webhook 1.1 进入企业微信中&#xff0c;添加群机器人&#xff0c;添加完成后可以获取到一个webhook的地址 1.2 群机器人企业微信接口的调用可以参考这个文件 https://developer.work.weixin.qq.com/document/path/99110#%E5%A6%82%E4%BD%…

C语言:求和1+1/2-1/3+1/4-1/5+……-1/99+1/100

#include<stdio.h> int main() {int i 0;double sum 0.0;int flag 1;for (i 1;i < 100;i){sum 1.0 / i * flag;flag -flag;}printf("sum%lf\n", sum);return 0; }

Centos7 配置Git

随笔记录 目录 1&#xff0c; 新建用户 2. 给用户设置密码相关操作 3. 为新用户添加sudo 权限 4. 配置Git 4.1 配置Git 4.2 查看id_ras.pub 5, 登录Git 配置SSH 秘钥 6. Centos7 登录Git 7. clone 指定branch到本地 8. 将新代码复制到指定路径 9. 上传指定代码 …

堆与二叉树(上)

本篇主要讲的是一些概念&#xff0c;推论和堆的实现&#xff08;核心在堆的实现这一块&#xff09; 涉及到的一些结论&#xff0c;证明放到最后&#xff0c;可以选择跳过&#xff0c;知识点过多&#xff0c;当复习一用差不多&#xff0c;如果是刚学这一块的&#xff0c;建议打…

微信小程序---自定义组件

目录 1.局部引用组件 2.全局引用组件 3.组件和页面的区别 4.自定义组件样式 5.properties属性 6.data和properties的区别 7.数据监听器 8.纯数据字段 9.自定义组件-组件的生命周期 lifetimes节点 10.组件所在的页面的生命周期 pageLifetimes节点 11.插槽 &#x…

安全算法(二):共享密钥加密、公开密钥加密、混合加密和迪菲-赫尔曼密钥交换

安全算法&#xff08;二&#xff09;&#xff1a;共享密钥加密、公开密钥加密、混合加密和迪菲-赫尔曼密钥交换 本章介绍了共享密钥加密、公开密钥加密&#xff0c;和两种加密方法混合使用的混合加密方法&#xff1b;最后介绍了迪菲-赫尔曼密钥交换。 加密数据的方法可以分为…

Transformer的学习

文章目录 Transformer1.了解Seq2Seq任务2.Transformer 整体架构3.Encoder的运作方式4.Decoder的运作方式5.AT 与 NAT6.Encoder 和 Decoder 之间的互动7.Training Transformer 1.了解Seq2Seq任务 NLP 的问题&#xff0c;都可以看做是 QA&#xff08;Question Answering&#x…

RFID工业识别系统的优势和价值

RFID是物联网感知层最重要的组成部分之一&#xff0c;它可以通过感知物品来实现智能化识别和管理&#xff0c;实现不同设备之间的互联。本文将深入探讨RFID工业识别系统的优势和价值&#xff0c;并探讨其实际应用的案例情况。 RFID工业识别系统的优势和价值 RFID作为物联网感知…