椋鸟数据结构笔记#3:链表

news2025/1/23 5:01:22

萌新的学习笔记,写错了恳请斧正。


目录

链表的定义

链表的分类

方向(单向还是双向)

头节点(哨兵节点)的有无

循环或不循环

8种分类

不带头单向不循环链表的实现

带头单向循环链表的实现

链表与顺序表的差异


链表的定义

链表是一种基于指针的,物理结构不连续而逻辑结构连续的数据结构。大概就是说,把一个一个数据存放在一个一个节点中,每一个节点可能创建在内存的不同区域,但是每个节点都包括了至少一个指向下一个节点的指针。这样,我们就可以通过指针来按顺序找到整个链表的数据。

我们一般创建一个结构体类型作为链表的节点,结构体的成员包括若干数据和若干指针,其中数据部分称为链表的数据域,指针部分称为链表的指针域。(有些指针属于数据,要具体分析其功能

链表的分类

方向(单向还是双向)

链表可以是单向的也可以是双向的。

单向代表链表每个节点的指针域指向其下一个节点,可以顺着指针一路向后寻找而不能反过来向前寻找;而双向链表的节点一般有两个指针,一个指向后一个节点,另一个指向前一个节点。

头节点(哨兵节点)的有无

头结点本身不存储任何实际的数据元素,而是作为链表的第一个节点存在,其主要作用是指向链表的第一个实际存储数据的节点。使用头结点的好处在于可以使链表的插入和删除操作更加统一和简洁,因为即使是在链表的开头进行操作,也不需要对链表进行特殊处理,从而避免了一些边界条件的检查

在不带头结点的链表中,插入新的第一个元素或删除现有的第一个元素时,需要特别处理链表的头指针,这可能会使代码变得复杂且容易出错。而在带有头结点的链表中,无论插入或删除操作发生在链表的哪个位置,操作流程都是统一的,因为头结点为链表提供了一个统一的入口

循环或不循环

如果链表的最后一个节点再次指向整个链表的第一个节点(哨兵节点或数据节点),那么这个链表就是循环的。循环的结构可以为实现很多比较复杂的数据处理功能带来便利。

8种分类

所以从上面3个角度考虑,链表一共可以分为8种(排列组合),但是最常用的有两种:不带头单向不循环链表(简称单链表)、带头双向循环链表

这两种链表中,单链表结构最简单,但是一般不会直接使用,而是作为一些更复杂的数据结构的子结果,也频繁出现在试题中。

而带头双向循环链表则是实际作为链表使用最频繁的,在实现诸多功能上都存在明显优势。

下面是8种链表的示意图:

不带头单向不循环链表的实现

头文件SList.h

//不带头单向不循环链表(single linked list)

#pragma once

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

//单链表节点的值类型
typedef int SLDataType;

//单链表节点
typedef struct SListNode
{
	SLDataType data;
	struct SListNode* next;
} SListNode;

//单链表的初始化
#define SListInit(pList) SListNode* pList = NULL

//单链表的销毁
void SListDestory(SListNode** ppList);

//单链表的头插
void SListPushFront(SListNode** ppList, SLDataType x);
//单链表的尾插
void SListPushBack(SListNode** ppList, SLDataType x);

//单链表指定位置后插入
void SListInsertAfter(SListNode* pos, SLDataType x);
//单链表指定位置前插入
void SListInsertBefore(SListNode** ppList, SListNode* pos, SLDataType x);

//单链表的头删
void SListPopFront(SListNode** ppList);
//单链表的尾删
void SListPopBack(SListNode** ppList);

//单链表删除指定位置的节点
void SListErase(SListNode** ppList, SListNode* pos);
//单链表指定位置后删除
void SListEraseAfter(SListNode* pos);
//单链表指定位置前删除
void SListEraseBefore(SListNode** ppList, SListNode* pos);

//单链表删除所有指定值的节点
void SListRemove(SListNode** ppList, SLDataType x);

//单链表查找
SListNode* SListFind(SListNode* pList, SLDataType x);
//单链表中间节点
SListNode* SListFindMidNode(SListNode* pList);

//单链表的长度
int SListSize(SListNode* pList);
//单链表的判空
int SListEmpty(SListNode* pList);

//单链表打印
void SListPrint(SListNode* pList);

//单链表逆序
void SListReverse(SListNode** ppList);

//单链表冒泡排序
void SListBubbleSort(SListNode** pList);

//合并两个有序链表
SListNode* SListMerge(SListNode* pList1, SListNode* pList2);

源文件SList.c

#include "SList.h"

//单链表的销毁
void SListDestory(SListNode** ppList)
{
	//断言
	assert(ppList);
	SListNode* cur = *ppList;
	while (cur)
	{
		SListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*ppList = NULL;
}

//新节点申请
SListNode* SListBuyNode(SLDataType x)
{
	SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
	if (newNode == NULL)
	{
		perror("malloc");
		exit(EXIT_FAILURE);
	}
	newNode->data = x;
	newNode->next = NULL;
	return newNode;
}

//单链表的头插
void SListPushFront(SListNode** ppList, SLDataType x)
{
	//断言
	assert(ppList);
	SListNode* newNode = SListBuyNode(x);
	newNode->next = *ppList;
	*ppList = newNode;
}
//单链表的尾插
void SListPushBack(SListNode** ppList, SLDataType x)
{
	//断言
	assert(ppList);
	SListNode* newNode = SListBuyNode(x);
	if (*ppList == NULL)
	{
		*ppList = newNode;
	}
	else
	{
		SListNode* cur = *ppList;
		while (cur->next)
		{
			cur = cur->next;
		}
		cur->next = newNode;
	}
}

//单链表指定位置后插入
void SListInsertAfter(SListNode* pos, SLDataType x)
{
	//断言
	assert(pos);
	SListNode* newNode = SListBuyNode(x);
	newNode->next = pos->next;
	pos->next = newNode;
}
//单链表指定位置前插入
void SListInsertBefore(SListNode** ppList, SListNode* pos, SLDataType x)
{
	//断言
	assert(ppList&&pos);
	if (*ppList == NULL || *ppList == pos)	//空链表或者pos为头节点
	{
		SListPushFront(ppList, x);
	}
	else
	{
		SListNode* cur = *ppList;
		while (cur->next != pos)
		{
			cur = cur->next;
		}
		SListNode* newNode = SListBuyNode(x);
		newNode->next = cur->next;
		cur->next = newNode;
	}
}

//单链表的头删
void SListPopFront(SListNode** ppList)
{
	//断言
	assert(ppList);
	if (*ppList == NULL)
	{
		return;
	}
	else
	{
		SListNode* next = (*ppList)->next;
		free(*ppList);
		*ppList = next;
	}
}
//单链表的尾删
void SListPopBack(SListNode** ppList)
{
	//断言
	assert(ppList);
	if (*ppList == NULL)
	{
		return;
	}
	else if ((*ppList)->next == NULL)
	{
		free(*ppList);
		*ppList = NULL;
	}
	else
	{
		SListNode* cur = *ppList;
		while (cur->next->next)
		{
			cur = cur->next;
		}
		free(cur->next);
		cur->next = NULL;
	}
}

//单链表删除指定位置的节点
void SListErase(SListNode** ppList, SListNode* pos)
{
	//断言
	assert(ppList&&pos);
	if (*ppList == NULL)
	{
		return;
	}
	else if (*ppList == pos)
	{
		SListPopFront(ppList);
	}
	else
	{
		SListNode* cur = *ppList;
		while (cur->next != pos)
		{
			cur = cur->next;
		}
		cur->next = pos->next;
		free(pos);
	}
}
//单链表指定位置后删除
void SListEraseAfter(SListNode* pos)
{
	//断言
	assert(pos);
	if (pos->next == NULL)
	{
		return;
	}
	else
	{
		SListNode* next = pos->next->next;
		free(pos->next);
		pos->next = next;
	}
}
//单链表指定位置前删除
void SListEraseBefore(SListNode** ppList, SListNode* pos)
{
	//断言
	assert(ppList&&pos);
	if (*ppList == NULL || *ppList == pos)	//空链表或者pos为头节点
	{
		return;
	}
	else if ((*ppList)->next == pos)	//pos为第二个节点
	{
		SListPopFront(ppList);
	}
	else
	{
		SListNode* cur = *ppList;
		while (cur->next->next != pos)
		{
			cur = cur->next;
		}
		free(cur->next);
		cur->next = pos;
	}
}

//单链表删除所有指定值的节点
void SListRemove(SListNode** ppList, SLDataType x)
{
	//断言
	assert(ppList);
	if (*ppList == NULL)
	{
		return;
	}
	else
	{
		SListNode* cur = *ppList;
		while (cur->next)
		{
			if (cur->next->data == x)
			{
				SListNode* next = cur->next->next;
				free(cur->next);
				cur->next = next;
			}
			else
			{
				cur = cur->next;
			}
		}
		if ((*ppList)->data == x)
		{
			SListPopFront(ppList);
		}
	}
}

//单链表查找
SListNode* SListFind(SListNode* pList, SLDataType x)
{
	//断言
	assert(pList);
	SListNode* cur = pList;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
//单链表中间节点
SListNode* SListFindMidNode(SListNode* pList)
{
	//断言
	assert(pList);
	SListNode* fast = pList;
	SListNode* slow = pList;
	while (fast && fast->next)
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	return slow;
}

//单链表的长度
int SListSize(SListNode* pList)
{
	//断言
	assert(pList);
	int count = 0;
	SListNode* cur = pList;
	while (cur)
	{
		count++;
		cur = cur->next;
	}
	return count;
}
//单链表的判空
int SListEmpty(SListNode* pList)
{
	return pList == NULL ? 1 : 0;
}

//单链表打印
void SListPrint(SListNode* pList)
{
	//断言
	assert(pList);
	SListNode* cur = pList;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

//单链表逆序
void SListReverse(SListNode** ppList)
{
	//断言
	assert(ppList);
	if (*ppList == NULL || (*ppList)->next == NULL)
	{
		return;
	}
	else
	{
		SListNode* cur = *ppList;
		SListNode* next = cur->next;
		SListNode* nextNext = next->next;
		while (next)
		{
			next->next = cur;
			cur = next;
			next = nextNext;
			if (nextNext)
			{
				nextNext = nextNext->next;
			}
		}
		(*ppList)->next = NULL;
		*ppList = cur;
	}
}

//单链表冒泡排序
void SListBubbleSort(SListNode** pList)
{
	//断言
	assert(pList);
	if (*pList == NULL || (*pList)->next == NULL)
	{
		return;
	}
	else
	{
		SListNode* tail = NULL;	//尾节点
		while (tail != *pList)	//只有一个节点时,tail==*pList
		{
			SListNode* cur = *pList;	//当前节点
			SListNode* next = cur->next;	//下一个节点
			SListNode* prev = NULL;	//当前节点的前一个节点
			while (next != tail)	//只有两个节点时,next==tail
			{
				if (cur->data > next->data)	//交换
				{
					if (cur == *pList)	//头节点交换
					{
						cur->next = next->next;
						next->next = cur;
						*pList = next;
						prev = next;
						next = cur->next;
					}
					else
					{
						cur->next = next->next;
						next->next = cur;
						prev->next = next;
						prev = next;
						next = cur->next;
					}
				}
				else	//不交换
				{
					prev = cur;
					cur = next;
					next = next->next;
				}
			}
			tail = cur;
		}
	}
}

//单链表合并
SListNode* SListMerge(SListNode* pList1, SListNode* pList2)
{
	if (!pList1)
	{
		return pList2;
	}
	if (!pList2)
	{
		return pList1;
	}
	SListNode* newList = NULL;
	SListNode* cur1 = pList1;
	SListNode* cur2 = pList2;
	SListNode* cur = NULL;
	while (cur1 && cur2)
	{
		if (cur1->data < cur2->data)
		{
			if (!newList)
			{
				newList = cur = cur1;
			}
			else
			{
				cur->next = cur1;
				cur = cur->next;
			}
			cur1 = cur1->next;
		}
		else
		{
			if (!newList)
			{
				newList = cur = cur2;
			}
			else
			{
				cur->next = cur2;
				cur = cur->next;
			}
			cur2 = cur2->next;
		}
	}
	if (cur1)
	{
		cur->next = cur1;
	}
	else
	{
		cur->next = cur2;
	}
	return newList;
}

带头单向循环链表的实现

头文件List.h

//带头双向不循环链表(List)

#pragma once

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

//定义数据类型
typedef int LTDataType;

//定义链表节点
typedef struct ListNode
{
	LTDataType data;
	struct ListNode* next;
	struct ListNode* prev;
} ListNode;

//申请节点
ListNode* BuyListNode(LTDataType x);

//初始化链表
ListNode* ListInit(void);
//销毁链表
void ListDestory(ListNode** pphead);

//打印
void ListPrint(ListNode* phead);

//尾插
void ListPushBack(ListNode* phead, LTDataType x);
//头插
void ListPushFront(ListNode* phead, LTDataType x);

//尾删
void ListPopBack(ListNode* phead);
//头删
void ListPopFront(ListNode* phead);

//查找
ListNode* ListFind(ListNode* phead, LTDataType x);

//在pos位置之后插入x
void ListInsert(ListNode* pos, LTDataType x);
//删除pos位置的节点
void ListErase(ListNode* pos);

源文件List.c

#include "List.h"

//申请节点
ListNode* BuyListNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		perror("malloc");
		exit(EXIT_FAILURE);
	}
	newnode->data = x;
	newnode->next = newnode->prev = NULL;
	return newnode;
}

//初始化链表
ListNode* ListInit(void)
{
	ListNode* phead = BuyListNode((LTDataType)0);
	phead->next = phead->prev = phead;
	return phead;
}
//销毁链表
void ListDestory(ListNode** pphead)
{
	//断言
	assert(pphead);
	if (*pphead == NULL)
	{
		return;
	}
	ListNode* phead = *pphead;
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
	*pphead = NULL;
} 

//打印
void ListPrint(ListNode* phead)
{
	//断言
	assert(phead);
	ListNode* cur = phead->next;
	printf("head->");
	while (cur != phead)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("tail\n");
}

//尾插
void ListPushBack(ListNode * phead, LTDataType x)
{
	//断言
	assert(phead);
	ListNode* tail = phead->prev;
	ListNode* newnode = BuyListNode(x);
	newnode->next = phead;
	newnode->prev = tail;
	tail->next = newnode;
	phead->prev = newnode;
}
//头插
void ListPushFront(ListNode* phead, LTDataType x)
{
	//断言
	ListNode* newnode = BuyListNode(x);
	newnode->next = phead->next;
	newnode->prev = phead;
	phead->next->prev = newnode;
	phead->next = newnode;
}

//尾删
void ListPopBack(ListNode* phead)
{
	//断言
	assert(phead);
	ListNode* tail = phead->prev;
	ListNode* prev = tail->prev;
	prev->next = phead;
	phead->prev = prev;
	free(tail);
}
//头删
void ListPopFront(ListNode* phead)
{
	//断言
	assert(phead);
	ListNode* first = phead->next;
	ListNode* second = first->next;
	phead->next = second;
	second->prev = phead;
	free(first);
}

//查找
ListNode* ListFind(ListNode* phead, LTDataType x)
{
	//断言
	assert(phead);
	ListNode* 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* newnode = BuyListNode(x);
	newnode->next = pos->next;
	newnode->prev = pos;
	pos->next->prev = newnode;
	pos->next = newnode;
}
//删除pos位置的节点
void ListErase(ListNode* pos)
{
	//断言
	assert(pos);
	ListNode* prev = pos->prev;
	ListNode* next = pos->next;
	prev->next = next;
	next->prev = prev;
	free(pos);
}

链表与顺序表的差异

区别链表顺序表
物理结构不连续连续
随机访问(通过下标任意的访问节点)不支持,O(N)支持,O(1)
任意位置插入删除只需要修改指针的方向即可可能需要大量挪移数据,效率低下
容量没有容量的概念需要管理容量,扩容
应用场景频繁发生任意位置插入时需要高效频繁访问各节点元素时
缓存命中(意味着CPU访问内存的效率)

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

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

相关文章

java全排列(力扣Leetcode46)

全排列 力扣原题链接 问题描述 给定一个不含重复数字的数组 nums&#xff0c;返回其所有可能的全排列。你可以按任意顺序返回答案。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示例 2…

FME学习之旅---day17

我们付出一些成本&#xff0c;时间的或者其他&#xff0c;最终总能收获一些什么。 【FME-HOW-TO系列】28 栅格邻域函数 RasterConvolver转换器说明&#xff1a; 接受包含栅格几何对象的输入要素&#xff0c;并在对所有波段应用卷积滤波 器后输出要素。 本人对栅格数据处理的较…

从易到难,推荐9个适合练手的C++项目

老有一些同学和我说学习了 C 以后&#xff0c;想要做些项目锻炼自己&#xff0c;让我从「简单到难」都推荐一些。 那有啥说的&#xff0c;必须推荐&#xff01;毕竟 C 的优质项目我见过太多了&#xff01; 下面我就按照「从易到难」的梯度&#xff0c;依次来推荐&#xff0c;…

反应式编程(一)什么是反应式编程

目录 一、背景二、反应式编程简介2.1 定义2.2 反应式编程的优势2.3 命令式编程 & 反应式编程 三、Reactor 入门3.1 Reactor 的核心类3.2 Reactor 中主要的方法1&#xff09;创建型方法2&#xff09;转化型方法3&#xff09;其他类型方法4&#xff09;举个例子 四、Reactor …

kafka学习笔记02(小滴课堂)

Kafka命令行生产者发送消息和消费者消费消息实战 已存在的kafka不能重复创建。 broker设置的是1&#xff0c;factor大于broker了&#xff0c;所以报错。 生产者发送消息&#xff1a; kafka列表出现了新的kafka。 我们使用这个kafka。 我们启动消费者&#xff1a; 我们现在不从…

机器学习--支持向量机(通俗版本+demo)

场景 假设我们要在一个在线零售平台上自动区分商品评论是正面的还是负面的。评论中的语言多种多样&#xff0c;且往往含有大量的非结构化文本数据&#xff0c;直接使用简单的规则来分类是非常困难。这时候我们采取支持向量机算法来分类是一个比较好的选择。 支持向量机 支持…

Find Any File (FAF) for Mac:您的专属文件搜索神器

在数字时代&#xff0c;我们的Mac硬盘中堆积着各式各样的文件&#xff0c;从工作文档到家庭照片&#xff0c;从音乐视频到学习资料&#xff0c;无一不体现出我们的生活和工作的丰富多彩。然而&#xff0c;当我们需要快速找到某个特定文件时&#xff0c;却常常在茫茫文件海中迷失…

PostgreSQL到Doris的迁移技巧:实时数据同步新选择!

PostgreSQL可以说是目前比较抢手的关系型数据库了&#xff0c;除了兼具多样功能和强大性能之外&#xff0c;还具备非常优秀的可扩展性&#xff0c;更重要的是它还开源&#xff0c;能火不是没有理由的。 虽然PostgreSQL很强大&#xff0c;但是它也有短板&#xff0c;相对于专业…

DHT22温湿度传感器驱动代码(C8T6)

最近做了一个小项目&#xff0c;总结了一下温湿度传感器dht22的驱动代码&#xff0c;方便大家使用。实测可用&#xff0c;注意修改自己的引脚还有初始化gpio即可。 DHT22.c #include "DHT22.h" #include "gpio.h" #include "usart.h" #include &…

数据处理库Pandas数据结构DataFrame

Dataframe是一种二维数据结构&#xff0c;数据以表格形式&#xff08;与Excel类似&#xff09;存储&#xff0c;有对应的行和列&#xff0c;如图3-3所示。它的每列可以是不同的值类型&#xff08;不像 ndarray 只能有一个 dtype&#xff09;。基本上可以把 DataFrame 看成是共享…

STM32 直接修改寄存器来输出内部时钟的方法

1. 在特殊情况下使能 MCO 功能的方法 在对某些不容易复现的问题进行代码调时&#xff0c;需要观察内部时钟的情况&#xff0c;但往往代码之前并没有使能 MCO 功能&#xff0c;在这种情况下就可以使用寄存器直接配置来输出内部时钟到GPIO 脚位上进行观察和测试。 下面的例子就…

泰迪智能科技荣获山东省“技能兴鲁”职业技能大赛优秀组织奖

近日&#xff0c;泰迪智能科技荣获了山东省“技能兴鲁”职业技能大赛——第四届山东省“云数”技能竞赛“优秀组织单位”。 据悉&#xff0c;山东省“技能兴鲁”职业技能大赛——第四届山东省“云数”技能竞赛是由山东电子学会、山东省信息产业协会主办的&#xff0c;该竞赛是通…

产品之美10| 小小提示词(hint),便于用户交互

最近AIGC功能火热&#xff0c;有文生图和图生图两种。当用户初次接触到文生图的时候&#xff0c;会有一刻停顿&#xff1a;我该怎用输入呢&#xff1f;这时候的hint就可以发挥作用了&#xff1a; 编辑框&#xff08;EditView)里面有可爱的小女孩&#xff0c;加风格卡通。用户看…

面试题1(京东)之HiveSql --- 难度:入门初级

第1题 有如下的用户访问数据 userIdvisitDatevisitCountu012017/1/215u022017/1/236u032017/1/228u042017/1/203u012017/1/236u012017/2/218u022017/1/236u012017/2/224 要求使用SQL统计出每个用户的累积访问次数&#xff0c;如下表所示&#xff1a; 用户id月份小计累积u01…

Linux+ARM 简单环境检测---软件部分

1、前言 这个是我学习linuxARM的在做的第一个软硬件结合项目&#xff0c;以往的类似这种整体类项目还是光单片机的时候&#xff0c;linux软件部分学习了差不多快一年了&#xff0c;因为各种事情耽搁&#xff0c;这个项目一直没有静下心来完成&#xff0c;不过终于哈哈哈哈搞完了…

摸鱼的时候可以干什么?

可以做什么&#xff1f;有了VScode&#xff0c;你想做啥都可以&#xff01; 1、刷知乎 上班总是忍不住刷知乎&#xff0c;但是又怕领导发现&#xff0c;这个插件可以帮助你悄无声息地愉快地浏览知乎&#xff0c;有多少人是用这款插件看到的这篇文章&#xff1f; 你甚至可以用 M…

Java反序列化JDK动态代理的关系

Java代理模式 为什么要学习代理模式&#xff1f;了解开发原理&#xff0c;才能明白漏洞的产生。这不仅仅是SpringAOP的底层&#xff01; [SpringAOP 和 SpringMVC] 代理模式的分类&#xff1a; 静态代理动态代理 静态代理 角色分析&#xff1a; 抽象角色&#xff1a;一般会…

【vue】一个小bug和key的引入

点击master Vue!删除后该list后输入框中的Jerry消失了 原因&#xff1a;vue当你更改元素时会在真实的dom中渲染并更新list。这两个goal是两个dom元素,触发点击事件后,vue并不会删除第一个dom元素,而是把第二个dom元素的动态内容({{ goal }} - {{ index }})复制到第一个dom元素…

Logback日志框架(超详细)

logback-classic-1.2.3.jarhttp://链接: https://pan.baidu.com/s/1cA3gVB_6DEA-cSFJN6MDGw 提取码: sn8i 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 logback-core-1.2.3.jarhttp://链接: https://pan.baidu.com/s/19eCsvsO72a9PTqpXvXxrgg 提取码: 5yp…

JHY-31复合电压继电器 额定电压Un=110VDC 板后接线 JOSEF约瑟

用途&#xff1a; JHY-31复合电压继电器使用于电力系统的继电保护线路中&#xff0c;作为各种类型故障的判别元件和电压闭锁元件。 继电器型号名称&#xff1a; 例:辅助直流工作电压为110V的复合电压继电器的订货代号为: JHY-31/110V。 工作原理&#xff1a; 继电器内部具有负…