带头双向循环链表:一种高效的数据结构


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

在这里插入图片描述

文章目录

    • 一、带头循环双向链表的概念及结构
    • 二、使用带头双向循环链表的优势及注意事项
    • 三、带头双向链表的创建
      • ✨3.1 准备工作✨
      • ✨3.2 创建返回链表的头结点✨
      • ✨3.3 双向链表销毁✨
      • ✨3.4 双向链表打印✨
      • ✨3.5 双向链表尾插✨
      • ✨3.6 双向链表尾删✨
      • ✨3.7 双向链表头插✨
      • ✨3.8 双向链表头删✨
      • ✨3.9 双向链表查找✨
      • ✨3.10 双向链表在pos的前面进行插入✨
      • ✨3.11 双向链表删除pos位置的节点✨
    • 四、源代码
      • 🌅4.1 List.h 文件
      • 🌅4.2 List.c 文件
      • 🌅4.3 Test.c 文件
      • 🌅4.4 测试结果

双向循环链表是一种复杂的数据结构,它结合了双向链表和循环链表的优点。与单向链表相比,双向链表可以双向遍历,而循环链表则可以在尾部链接到头部,形成一个闭环。这种数据结构在某些应用场景下非常有用,比如事件处理、图形界面、内存管理等。

一、带头循环双向链表的概念及结构

双向循环链表是一种特殊类型的链表,它由一系列节点组成,每个节点包含一个数据域两个指针域。其中一个指针指向下一个节点,另一个指针指向前一个节点。在双向循环链表中,首节点的前一个节点是尾节点,尾节点的下一个节点是首节点,形成一个闭环

在这里插入图片描述

二、使用带头双向循环链表的优势及注意事项

【优势】:

  1. 高效遍历:由于带头双向循环链表可以双向遍历,因此可以在O(1)时间内访问任何节点。
  2. 内存高效:与双向链表相比,带头双向循环链表不需要额外的内存来存储头部节点。
  3. 插入和删除操作高效:在带头双向循环链表中插入和删除节点时,只需调整指针即可,无需移动大量数据。

【注意事项】:

  1. 初始化:在创建带头双向循环链表时,需要正确初始化所有节点的指针。
  2. 异常处理:在进行插入、删除等操作时,需要处理指针异常情况,如空指针或无效指针。
  3. 内存管理:在使用带头双向循环链表时,需要正确管理内存,避免内存泄漏或野指针。

三、带头双向链表的创建

✨3.1 准备工作✨

将代码分成三个文件可以提高代码的可读性、可维护性和可重用性。具体来说,三个文件可以分别关注以下方面:

  1. 配置文件:用于存储应用程序的配置信息,如数据库连接信息、应用程序名称、应用程序版本等。该文件可以在应用程序的整个生命周期内进行维护和管理,并且可以轻松地与其他开发人员共享。
  2. 模块文件:用于存储应用程序的各个模块,如用户管理、订单管理、产品管理等。每个模块都可以单独维护和测试,并且可以在不同的应用程序中重复使用。这有助于降低代码冗余和提高代码的可重用性。
  3. 入口文件:用于定义应用程序的入口,如路由、请求处理等。该文件可以控制应用程序的整个流程,并且可以轻松地与其他开发人员共享。

通过将代码分成三个文件,可以更好地组织代码结构,使其更加清晰和易于维护。同时,这也使得代码更易于测试和调试,并且可以更好地支持代码重构和优化。

在这里插入图片描述

#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* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

✨3.2 创建返回链表的头结点✨

动态申请一个节点作为双向链表的头节点。并将头节点的 prev 指向自己,next也指向自己,表明这是一个双向链表,且链表为空。

// 创建返回链表的头结点.
ListNode* ListCreate()
{
	ListNode* head = (ListNode*)malloc(sizeof(ListNode));
	if (head == NULL)
	{
		perror("ListCreate --> malloc");
		return;
	}
	head->data = -1;
	head->prev = head;
	head->next = head;
	return head;
}

✨3.3 双向链表销毁✨

从链表的第二个节点开始,逐个释放链表中的节点,直到回到头节点并释放头节点的内存空间。这样做可以确保链表中的所有节点都被正确释放,防止内存泄漏。

// 双向链表销毁
void ListDestory(ListNode* pHead)
{
	assert(pHead);
	ListNode* cur = pHead->next;
	while (cur != pHead)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next; 
	}
	free(pHead);
	printf("双链表销毁成功!\n");
}

✨3.4 双向链表打印✨

// 双向链表打印
void ListPrint(ListNode* pHead)
{
	assert(pHead);
	ListNode* cur = pHead->next;
	printf("哨兵位 <--> ");
	while (cur != pHead)
	{
		printf("%d <--> ", cur->data);
		cur = cur->next;
	}
	printf("哨兵位\n");
}

✨3.5 双向链表尾插✨

在进行插入节点之前,无论是头插还是尾插都需要申请一个新的节点,于是可以把此步骤成一个函数,减少代码的冗余。

//申请一个节点
ListNode* CreateLTNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		perror("CreateLTNode --> malloc");
		return;
	}

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

	return newnode;
}
  1. 首先,创建一个新的节点newnode,并将数据x存储在其中。
  2. newnodeprev指针指向当前链表的第一个节点pHead的前一个节点,即pHead->prev
  3. newnodenext指针指向当前链表的第一个节点pHead
  4. 将当前链表的第一个节点pHead的前一个节点的next指针指向新节点newnode
  5. 将当前链表的第一个节点pHeadprev指针指向新节点newnode

通过以上步骤,新节点被插入到双向链表的尾部,并且链表中的其他节点仍然保持其原始顺序和链接关系。这样做可以确保新节点被正确地添加到链表中,并且不会破坏链表的结构。

// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
	assert(pHead);
	ListNode* newnode = CreateLTNode(x);

	//pHead           pHead->prev  newnode
	newnode->prev = pHead->prev; 
	newnode->next = pHead;
	pHead->prev->next = newnode;
	pHead->prev = newnode;
}

✨3.6 双向链表尾删✨

  1. 首先,获取链表的最后一个节点tail,它应该是头节点pHead的前一个节点(即pHead->prev)。
  2. 接着,获取最后一个节点的前一个节点tailPrev
  3. 将头节点pHeadprev指针指向最后一个节点的前一个节点tailPrev,从而将最后一个节点从链表中间删除。
  4. 将最后一个节点的前一个节点的next指针指向头节点pHead,从而将头节点和最后一个节点连接起来。
  5. 最后,释放最后一个节点的内存空间。
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
	assert(pHead);
	assert(pHead->next!=pHead);//链表不能为空

	ListNode* tail = pHead->prev;
	ListNode* tailPrev = tail->prev;
	// pHead     tailPrev tail
	pHead->prev = tailPrev;
	tailPrev->next = pHead;

	free(tail);
}

✨3.7 双向链表头插✨

  1. 首先,创建一个新的节点newnode,并将数据x存储在其中。
  2. 将新节点的prev指针指向当前链表的第一个节点pHead
  3. 将新节点的next指针指向当前链表的第一个节点的下一个节点,即pHead->next
  4. 将当前链表的第一个节点的next指针指向新节点newnode
  5. 将当前链表的第一个节点的下一个节点的prev指针指向新节点newnode

通过以上步骤,新节点被插入到双向链表的头部,并且链表中的其他节点仍然保持其原始顺序和链接关系。这样做可以确保新节点被正确地添加到链表中,并且不会破坏链表的结构。

// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
	assert(pHead);
	ListNode* newnode = CreateLTNode(x);

	ListNode* rear = pHead->next;
	pHead->next = newnode;
	newnode->prev = pHead;
	newnode->next = rear;
	rear->prev = newnode;
}

✨3.8 双向链表头删✨

  1. 首先,获取链表的第一个节点cur,它应该是头节点pHead的下一个节点(即pHead->next)。
  2. 将头节点的next指针指向第一个节点的下一个节点,从而将第一个节点从链表中间删除。
  3. 将第一个节点的下一个节点的prev指针指向头节点pHead,从而将头节点和第一个节点连接起来。
  4. 最后,释放第一个节点的内存空间。
// 双向链表头删
void ListPopFront(ListNode* pHead)
{
	assert(pHead);
	assert(pHead->next != pHead);

	ListNode* cur = pHead->next;
	pHead->next = cur->next;
	cur->next->prev = pHead;

	free(cur);
}

✨3.9 双向链表查找✨

  1. 首先,从链表的第二个节点开始(即pHead->next),遍历链表的每个节点。
  2. 对于每个节点,检查其存储的数据是否与要查找的数据x相等。
  3. 如果找到了匹配的节点,则返回该节点。
  4. 如果遍历完整个链表都没有找到匹配的节点,则返回空指针(NULL)。
// 双向链表查找
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;//如果没找到,返回空
}

✨3.10 双向链表在pos的前面进行插入✨

  1. 首先,创建一个新的节点newnode,并将数据x存储在其中。
  2. 获取要插入位置的前一个节点_prev
  3. 将前一个节点的next指针指向新节点newnode
  4. 将新节点的prev指针指向前一个节点_prev
  5. 将新节点的next指针指向当前节点pos
  6. 将当前节点的prev指针指向新节点newnode

通过以上步骤,新节点被插入到指定位置的前面,并且链表中的其他节点仍然保持其原始顺序和链接关系。这样做可以确保新节点被正确地添加到链表中,并且不会破坏链表的结构。

// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);
	ListNode* newnode = CreateLTNode(x);
	ListNode* _prev = pos->prev;

	// _prev newnode pos
	_prev->next = newnode;
	newnode->prev = _prev;
	newnode->next = pos;
	pos->prev = newnode;
}

✨3.11 双向链表删除pos位置的节点✨

  1. 首先,确保要删除的节点pos不是空指针。
  2. 获取要删除节点的前一个节点_prev和后一个节点rear
  3. 将前一个节点的next指针指向后一个节点,从而将要删除的节点从链表中间删除。
  4. 将后一个节点的prev指针指向前一个节点,从而将前一个节点和后一个节点连接起来。
  5. 释放要删除的节点的内存空间。
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* _prev = pos->prev;
	ListNode* rear = pos->next;

	_prev->next = rear;
	rear->prev = _prev;

	free(pos);
}

四、源代码

🌅4.1 List.h 文件

#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* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

🌅4.2 List.c 文件

#define _CRT_SECURE_NO_WARNINGS 1

#include "List.h"

//申请一个节点
ListNode* CreateLTNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		perror("CreateLTNode --> malloc");
		return;
	}

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

	return newnode;
}
// 创建返回链表的头结点.
ListNode* ListCreate()
{
	ListNode* head = (ListNode*)malloc(sizeof(ListNode));
	if (head == NULL)
	{
		perror("ListCreate --> malloc");
		return;
	}
	head->data = -1;
	head->prev = head;
	head->next = head;
	return head;
}
// 双向链表销毁
void ListDestory(ListNode* pHead)
{
	assert(pHead);
	ListNode* cur = pHead->next;
	while (cur != pHead)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next; 
	}
	free(pHead);
	printf("双链表销毁成功!\n");
}
// 双向链表打印
void ListPrint(ListNode* pHead)
{
	assert(pHead);
	ListNode* cur = pHead->next;
	printf("哨兵位 <--> ");
	while (cur != pHead)
	{
		printf("%d <--> ", cur->data);
		cur = cur->next;
	}
	printf("哨兵位\n");
}
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
	assert(pHead);
	ListNode* newnode = CreateLTNode(x);

	//pHead           pHead->prev  newnode
	newnode->prev = pHead->prev; 
	newnode->next = pHead;
	pHead->prev->next = newnode;
	pHead->prev = newnode;
}
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
	assert(pHead);
	assert(pHead->next!=pHead);//链表不能为空

	ListNode* tail = pHead->prev;
	ListNode* tailPrev = tail->prev;
	// pHead     tailPrev tail
	pHead->prev = tailPrev;
	tailPrev->next = pHead;

	free(tail);
}
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
	assert(pHead);
	ListNode* newnode = CreateLTNode(x);

	ListNode* rear = pHead->next;
	pHead->next = newnode;
	newnode->prev = pHead;
	newnode->next = rear;
	rear->prev = newnode;
}
// 双向链表头删
void ListPopFront(ListNode* pHead)
{
	assert(pHead);
	assert(pHead->next != pHead);

	ListNode* cur = pHead->next;
	pHead->next = cur->next;
	cur->next->prev = pHead;

	free(cur);
}
// 双向链表查找
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的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);
	ListNode* newnode = CreateLTNode(x);
	ListNode* _prev = pos->prev;

	// _prev newnode pos
	_prev->next = newnode;
	newnode->prev = _prev;
	newnode->next = pos;
	pos->prev = newnode;
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* _prev = pos->prev;
	ListNode* rear = pos->next;

	_prev->next = rear;
	rear->prev = _prev;

	free(pos);
}

🌅4.3 Test.c 文件

#define _CRT_SECURE_NO_WARNINGS 1

#include "List.h"


void Test1()
{
	ListNode* plist = ListCreate();
	//尾插1、2、3
	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPrint(plist);
	//头插5、4
	ListPushFront(plist, 5);
	ListPushFront(plist, 4);
	ListPrint(plist);
	//查找元素3,找到返回节点地址,没找到返回空
	ListNode* pos = ListFind(plist, 3);
	if (pos)
	{
		printf("找到了\n");
	}
	else
	{
		printf("没找到\n");
	}
	//在3前面插入30
	ListInsert(pos, 30);
	ListPrint(plist); 
	//删除3
	if (pos)
	{
		ListErase(pos);
		pos = NULL;
	}
	ListPrint(plist);
	//尾删两次
	ListPopBack(plist);
	ListPopBack(plist);
	ListPrint(plist);
	//头删两次
	ListPopFront(plist);
	ListPopFront(plist);
	ListPrint(plist);
	//销毁链表
	ListDestory(plist);
	plist = NULL;
}


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

🌅4.4 测试结果

在这里插入图片描述


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

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

相关文章

qt-C++笔记之addItem(), addWidget(), addLayout()

qt-C笔记之addItem(), addWidget(), addLayout() code review! 文章目录 qt-C笔记之addItem(), addWidget(), addLayout()0.《官方文档》相关示例截图1.ChatGPT解释2.《Qt 5.12实战》相关示例截图《Qt 5.12实战》&#xff1a;5.6 组合框 3.addWidget()4.addWidget()和addChil…

抓取检测(Grasp Dection)

抓取检测 抓取检测被定义为能够识别任何给定图像中物体的抓取点或抓取姿势。抓取策略应确保对新物体的稳定性、任务兼容性和适应性&#xff0c;抓取质量可通过物体上接触点的位置和手的配置来测量。为了掌握一个新的对象&#xff0c;完成以下任务&#xff0c;有分析方法和经验…

基于SSM的职业高中智慧作业试题系统设计

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;JSP 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 一、…

绘制彩色正多边形-第11届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第10讲。 绘制彩色正多边形…

Golang语言基础之切片

概述 数组的长度是固定的并且数组长度属于类型的一部分&#xff0c;所以数组有很多的局限性 func arraySum(x [3]int) int{sum : 0for _, v : range x{sum sum v}return sum } 这个求和函数只能接受 [3]int 类型&#xff0c;其他的都不支持。 切片 切片&#xff08;Slic…

一文彻底弄懂动态规划【DP】

动态规划是一种重要的算法&#xff0c;它能解决很多看似复杂的问题&#xff0c;关键在于找到问题的子问题结构&#xff0c;并根据子问题的解决方式来解决原问题。首先要了解的是动态规划的基本思想&#xff1a; 动态规划的基本思想是&#xff1a;将一个复杂的问题分解为一系列…

Qt将打印信息输出到文件

将打印信息&#xff08;qDebug、qInfo、qWarning、qCritial等&#xff09;输出到指定文件来以实现简单的日志功能。 #include "mainwindow.h" #include <QApplication> #include <QLoggingCategory> #include <QMutex> #include <QDateTime>…

Windows安装MySQL8.2

Windows安装MySQL8.2 三种安装模式 默认自定义完整 本案例选择自定义 选择安装目录 勾选 Run MySQL Configurator 配置MYSQL 默认为开发者模式 在 Config Type 下拉列表中选择数据中心 设置 root 账号密码

【专题】【数列极限】

【整体思路】 【常用不等式】

前后端分离部署https

引用&#xff1a;https://blog.csdn.net/weixin_35676679/article/details/127841598 前后端部署&#xff0c;&#xff0c;一般用的是nginx和java&#xff0c;&#xff0c;&#xff0c; 下载SSL证书&#xff1a; java配置https 将证书配置到springboot中 server:port: 544…

动态规划 | 打家劫舍1、2、3

198. 打家劫舍 https://leetcode.cn/problems/house-robber/description/ dp[i] 表示 考虑到下标为 i &#xff08;包括i&#xff09;的房子&#xff0c;可以偷到的最大金额。 dp[i] 有两个状态&#xff0c;分别是 偷 和 不偷。 偷&#xff0c;则需要考虑前 i-2 天的最大金额…

Google Colab 现已支持直接使用 transformers 库

Google Colab&#xff0c;全称 Colaboratory&#xff0c;是 Google Research 团队开发的一款产品。在 Colab 中&#xff0c;任何人都可以通过浏览器编写和执行任意 Python 代码。它尤其适合机器学习、数据分析和教育目的。从技术上来说&#xff0c;Colab 是一种托管式 Jupyter …

Mysql窗口函数

1 什么是窗口函数 MySQL从8.0开始支持窗口函数&#xff0c;有的也叫分析函数&#xff08;处理相对复杂的报表统计分析场景&#xff09;&#xff0c;这个功能在大多商业数据库和部分开源数据库中早已支持。 窗口函数&#xff1a;窗口、函数&#xff08;应用在窗口内的函数&…

Dockerfile与Docker网络

一、Dockerfile 1、概念&#xff1a; Dockerfile是用来构建docker镜像的文本文件&#xff0c;是由构建镜像所需要的指令和参数构建的脚本。 2、构建步骤&#xff1a; ① 编写Dockerfile文件 ② docker build命令构建镜像 ③ docker run依据镜像运行容器实例 Dockerfile …

深入理解:Class.getResource与ClassLoader.getResource使用区别

深入理解&#xff1a;Class.getResource与ClassLoader.getResource使用区别 一作用&#xff1a;都是使用类的类加载器来读取某个文件&#xff0c;从而获取该文件的URL对象二Class.getResource()方法读取文件&#xff1a;1.若文件路径以“/”开头&#xff0c;则该方法会从classp…

洛谷 P9516 color C++代码

目录 前言 思路点拨 AC代码 结尾 前言 今天我们来做洛谷上的一道题目。 网址&#xff1a;color - 洛谷 题目&#xff1a; 思路点拨 这题就是if-else判断输入的五个数据和不就OK了&#xff1f; 在这里我的估值是183&#xff08;截止2023.12.3&#xff09;&#xff0c;热…

软件工程单选多选补充

2. 4. 5. 6. 7. 8. 9. 10. 12。 13.

Zabbix监控接收SNMPTrap消息与SNMPTT结合

一.SNMP 协议 1.协议介绍 snmp 协议是日常使用的较多的一种协议&#xff0c;绝大多数网络设备/存储等都支持 snmp 协议&#xff0c;通过此协议可以实现设备状态的监控及管理。 2.主要组成 SNMP 协议包括以下三个部分: SNMP Agent&#xff1a;负责处理 snmp 请求&#xff0c…

k8s中批量处理Pod应用的Job和CronJob控制器、处理守护型pod的DaemonSet控制器介绍

目录 一.Job控制器 1.简介 2.Jobs较完整解释 3.示例演示 4.注意&#xff1a;如上例的话&#xff0c;执行“kubectl delete -f myJob.yaml”就可以将job删掉 二.CronJob&#xff08;简写为cj&#xff09; 1.简介 2.CronJob较完整解释 3.案例演示 4.如上例的话&#xf…
最新文章