01.Queue-Basic

1. 队列简介

队列(Queue):一种线性表数据结构,是一种只允许在表的一端进行插入操作,而在表的另一端进行删除操作的线性表。

我们把队列中允许插入的一端称为 「队尾(rear)」;把允许删除的另一端称为 「队头(front)」。当表中没有任何数据元素时,称之为 「空队」

队列有两种基本操作:「插入操作」「删除操作」

  • 队列的插入操作又称为「入队」。
  • 队列的删除操作又称为「出队」。

简单来说,队列是一种 「先进先出(First In First Out)」 的线性表,简称为 「FIFO 结构」

我们可以从两个方面来解释一下队列的定义:

  • 第一个方面是 「线性表」

队列首先是一个线性表,队列中元素具有前驱后继的线性关系。队列中元素按照 a 1 , a 2 , . . . , a n a_1, a_2, ... , a_n a1,a2,...,an 的次序依次入队。队头元素为 a 1 a_1 a1,队尾元素为 a n a_n an

  • 第二个方面是 「先进先出原则」

根据队列的定义,最先进入队列的元素在队头,最后进入队列的元素在队尾。每次从队列中删除的总是队头元素,即最先进入队列的元素。也就是说,元素进入队列或者退出队列是按照「先进先出(First In First Out)」的原则进行的。

2. 队列的顺序存储与链式存储

和线性表类似,队列有两种存储表示方法:「顺序存储的队列」「链式存储的队列」

  • 「顺序存储的队列」:利用一组地址连续的存储单元依次存放队列中从队头到队尾的元素,同时使用指针 front 指向队头元素在队列中的位置,使用指针 rear 指示队尾元素在队列中的位置。
  • 「链式存储的队列」:利用单链表的方式来实现队列。队列中元素按照插入顺序依次插入到链表的第一个节点之后,并使用队头指针 front 指向链表头节点位置,也就是队头元素,rear 指向链表尾部位置,也就是队尾元素。

注意:frontrear 的指向位置并不完全固定。有时候算法设计上的方便以及代码简洁,也会使 front 指向队头元素所在位置的前一个位置。rear 也可能指向队尾元素在队列位置的下一个位置。具体还是要看算法是如何实现的。

在描述队列的顺序存储与链式存储具体实现之前,我们先来看看队列具有哪些基本操作。

2.1 队列的基本操作

  • 初始化空队列:创建一个空队列,定义队列的大小 size,以及队头元素指针 front,队尾指针 rear

  • 判断队列是否为空:当队列为空时,返回 True。当队列不为空时,返回 False。一般只用于「出队操作」和「获取队头元素操作」中。

  • 判断队列是否已满:当队列已满时,返回 True,当队列未满时,返回 False。一般只用于顺序队列中插入元素操作中。

  • 插入元素(入队):相当于在线性表最后一个数据元素后面插入一个新的数据元素。并改变队尾指针 rear 的指向位置。

  • 删除元素(出队):相当于在线性表中删除第一个数据元素。并改变队头指针 front 的指向位置。

  • 获取队头元素:相当于获取线性表中第一个数据元素。与插入元素(入队)、删除元素(出队)不同的是,该操作并不改变队头指针 front 的指向位置。

  • 获取队尾元素:相当于获取线性表中最后一个数据元素。与插入元素(入队)、删除元素(出队)不同的是,该操作并不改变队尾指针 rear 的指向位置。

接下来我们来看一下队列的顺序存储与链式存储两种不同的实现方式。

2.2 队列的顺序存储实现

队列最简单的实现方式就是借助于一个数组来描述队列的顺序存储结构。在 Python 中我们可以借助列表 list 来实现。

2.2.1 队列的顺序存储基本描述

为了算法设计上的方便以及算法本身的简单,我们约定:队头指针 self.front 指向队头元素所在位置的前一个位置,而队尾指针 self.rear 指向队尾元素所在位置。

  • 初始化空队列:创建一个空队列 self.queue,定义队列大小 self.size。令队头指针 self.front 和队尾指针 self.rear 都指向 -1。即 self.front = self.rear = -1
  • 判断队列是否为空:根据 self.frontself.rear 的指向位置关系进行判断。如果队头指针 self.front 和队尾指针 self.rear 相等,则说明队列为空。否则,队列不为空。
  • 判断队列是否已满:如果 self.rear 指向队列最后一个位置,即 self.rear == self.size - 1,则说明队列已满。否则,队列未满。
  • 插入元素(入队):先判断队列是否已满,已满直接抛出异常。如果队列不满,则将队尾指针 self.rear 向右移动一位,并进行赋值操作。此时 self.rear 指向队尾元素。
  • 删除元素(出队):先判断队列是否为空,为空直接抛出异常。如果队列不为空,则将队头指针 self.front 指向元素赋值为 None,并将 self.front 向右移动一位。
  • 获取队头元素:先判断队列是否为空,为空直接抛出异常。如果队列不为空,因为 self.front 指向队头元素所在位置的前一个位置,所以队头元素在 self.front 后面一个位置上,返回 self.queue[self.front + 1]
  • 获取队尾元素:先判断队列是否为空,为空直接抛出异常。如果不为空,因为 self.rear 指向队尾元素所在位置,所以直接返回 self.queue[self.rear]
2.2.2 队列的顺序存储实现代码
class Queue:
    # 初始化空队列
    def __init__(self, size=100):
        self.size = size
        self.queue = [None for _ in range(size)]
        self.front = -1
        self.rear = -1
        
    # 判断队列是否为空
    def is_empty(self):
        return self.front == self.rear
    
    # 判断队列是否已满
    def is_full(self):
        return self.rear + 1 == self.size
    
    # 入队操作
    def enqueue(self, value):
        if self.is_full():
            raise Exception('Queue is full')
        else:
            self.rear += 1
            self.queue[self.rear] = value
            
    # 出队操作
    def dequeue(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            self.front += 1
            return self.queue[self.front]
        
    # 获取队头元素
    def front_value(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            return self.queue[self.front + 1]
    
    # 获取队尾元素
    def rear_value(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            return self.queue[self.rear]

2.3 循环队列的顺序存储实现

在「2.2 队列的顺序存储实现」中,如果队列中第 0 ~ size - 1 位置均被队列元素占用时,此时队列已满(即 self.rear == self.size - 1),再进行入队操作就会抛出队列已满的异常。

而由于出队操作总是删除当前的队头元素,将 self.front 进行右移,而插入操作又总是在队尾进行。经过不断的出队、入队操作,队列的变化就像是使队列整体向右移动。

当队尾指针满足 self.rear == self.size - 1 条件时,此时再进行入队操作就会抛出队列已满的异常。而之前因为出队操作而产生空余位置也没有利用上,这就造成了「假溢出」问题。

为了解决「假溢出」问题,有两种做法:

  • 第一种:每一次删除队头元素之后,就将整个队列往前移动 1 个位置。其代码如下所示:
# 出队操作
def dequeue(self):
    if self.is_empty():
        raise Exception('Queue is empty')
    else:
        value = self.queue[0]
        for i in range(self.rear):
            self.queue[i] = self.queue[i + 1]
        return value

这种情况下,队头指针似乎用不到了。因为队头指针总是在队列的第 0 个位置。但是因为删除操作涉及到整个队列元素的移动,所以每次删除操作的时间复杂度就从 O ( 1 ) O(1) O(1) 变为了 O ( n ) O(n) O(n)。所以这种方式不太可取。

  • 第二种:将队列想象成为头尾相连的循环表,利用数学中的求模运算,使得空间得以重复利用,这样就解决了问题。

在进行插入操作时,如果队列的第 self.size - 1 个位置被占用之后,只要队列前面还有可用空间,新的元素加入队列时就可以从第 0 个位置开始继续插入。

我们约定:self.size 为循环队列的最大元素个数。队头指针 self.front 指向队头元素所在位置的前一个位置,而队尾指针 self.rear 指向队尾元素所在位置。则:

  1. 插入元素(入队)时:队尾指针循环前进 1 个位置,即 self.rear = (self.rear + 1) % self.size
  2. 删除元素(出队)时:队头指针循环前进 1 个位置,即 self.front = (self.front + 1) % self.size

注意

  • 循环队列在一开始初始化,队列为空时,满足条件self.front == self.rear
  • 而当充满队列后,仍满足条件 self.front == self.rear

这种情况下就无法判断「队列为空」还是「队列为满」了。

为了区分循环队列中「队列为空」还是「队列已满」的情况,有多种处理方式:

  • 方式 1:增加表示队列中元素个数的变量 self.count,用来以区分队列已满还是队列为空。在入队、出队过程中不断更新元素个数 self.count 的值。
    • 队列已满条件为:队列中元素个数等于队列整体容量,即 self.count == self.size
    • 队空为空条件为:队列中元素个数等于 0,即 self.count == 0
  • 方式 2:增加标记变量 self.tag,用来以区分队列已满还是队列为空。
    • 队列已满条件为:self.tag == 1 的情况下,因插入导致 self.front == self.rear
    • 队列为空条件为:在 self.tag == 0 的情况下,因删除导致 self.front == self.rear
  • 方式 3:特意空出来一个位置用于区分队列已满还是队列为空。入队时少用一个队列单元,即约定以「队头指针在队尾指针的下一位置」作为队满的标志。
    • 队列已满条件为:队头指针在队尾指针的下一位置,即 (self.rear + 1) % self.size == self.front
    • 队列为空条件为:队头指针等于队尾指针,即 self.front == self.rear
2.3.1 循环队列的顺序存储基本描述

下面我们以「方式 3」中特意空出来一个位置的处理方式为例,对循环队列的顺序存储做一下基本描述。

我们约定:self.size 为循环队列的最大元素个数。队头指针 self.front 指向队头元素所在位置的前一个位置,而队尾指针 self.rear 指向队尾元素所在位置。

  • 初始化空队列:创建一个空队列,定义队列大小为 self.size + 1。令队头指针 self.front 和队尾指针 self.rear 都指向 0。即 self.front = self.rear = 0
  • 判断队列是否为空:根据 self.frontself.rear 的指向位置进行判断。根据约定,如果队头指针 self.front 和队尾指针 self.rear 相等,则说明队列为空。否则,队列不为空。
  • 判断队列是否已满:队头指针在队尾指针的下一位置,即 (self.rear + 1) % self.size == self.front,则说明队列已满。否则,队列未满。
  • 插入元素(入队):先判断队列是否已满,已满直接抛出异常。如果不满,则将队尾指针 self.rear 向右循环移动一位,并进行赋值操作。此时 self.rear 指向队尾元素。
  • 删除元素(出队):先判断队列是否为空,为空直接抛出异常。如果不为空,则将队头指针 self.front 指向元素赋值为 None,并将 self.front 向右循环移动一位。
  • 获取队头元素:先判断队列是否为空,为空直接抛出异常。如果不为空,因为 self.front 指向队头元素所在位置的前一个位置,所以队头元素在 self.front 后一个位置上,返回 self.queue[(self.front + 1) % self.size]
  • 获取队尾元素:先判断队列是否为空,为空直接抛出异常。如果不为空,因为 self.rear 指向队尾元素所在位置,所以直接返回 self.queue[self.rear]
2.3.2 循环队列的顺序存储实现代码
class Queue:
    # 初始化空队列
    def __init__(self, size=100):
        self.size = size + 1
        self.queue = [None for _ in range(size + 1)]
        self.front = 0
        self.rear = 0
        
    # 判断队列是否为空
    def is_empty(self):
        return self.front == self.rear
    
    # 判断队列是否已满
    def is_full(self):
        return (self.rear + 1) % self.size == self.front
    
    # 入队操作
    def enqueue(self, value):
        if self.is_full():
            raise Exception('Queue is full')
        else:
            self.rear = (self.rear + 1) % self.size
            self.queue[self.rear] = value
            
    # 出队操作
    def dequeue(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            self.queue[self.front] = None
            self.front = (self.front + 1) % self.size
            return self.queue[self.front]
        
    # 获取队头元素
    def front_value(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            value = self.queue[(self.front + 1) % self.size]
            return value
        
    # 获取队尾元素
    def rear_value(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            value = self.queue[self.rear]
            return value

2.3 队列的链式存储实现

对于在使用过程中数据元素变动较大,或者说频繁进行插入和删除操作的数据结构来说,采用链式存储结构比顺序存储结构更加合适。

所以我们可以采用链式存储结构来实现队列。

  1. 我们用一个线性链表来表示队列,队列中的每一个元素对应链表中的一个链节点。
  2. 再把线性链表的第 1 个节点定义为队头指针 front,在链表最后的链节点建立指针 rear 作为队尾指针。
  3. 最后限定只能在链表队头进行删除操作,在链表队尾进行插入操作,这样整个线性链表就构成了一个队列。
2.3.1 队列的链式存储基本描述

我们约定:队头指针 self.front 指向队头元素所在位置的前一个位置,而队尾指针 self.rear 指向队尾元素所在位置。

  • 初始化空队列:建立一个链表头节点 self.head,令队头指针 self.front 和队尾指针 self.rear 都指向 head。即 self.front = self.rear = head
  • 判断队列是否为空:根据 self.frontself.rear 的指向位置进行判断。根据约定,如果队头指针 self.front 等于队尾指针 self.rear,则说明队列为空。否则,队列不为空。
  • 插入元素(入队):创建值为 value 的链表节点,插入到链表末尾,并令队尾指针 self.rear 沿着链表移动 1 位到链表末尾。此时 self.rear 指向队尾元素。
  • 删除元素(出队):先判断队列是否为空,为空直接抛出异常。如果不为空,则获取队头指针 self.front 下一个位置节点上的值,并将 self.front 沿着链表移动 1 位。如果 self.front 下一个位置是 self.rear,则说明队列为空,此时,将 self.rear 赋值为 self.front,令其相等。
  • 获取队头元素:先判断队列是否为空,为空直接抛出异常。如果不为空,因为 self.front 指向队头元素所在位置的前一个位置,所以队头元素在 self.front 后一个位置上,返回 self.front.next.value
  • 获取队尾元素:先判断队列是否为空,为空直接抛出异常。如果不为空,因为 self.rear 指向队尾元素所在位置,所以直接返回 self.rear.value
2.3.2 队列的链式存储实现代码
class Node:
    def __init__(self, value):
        self.value = value
        self.next = None
        
class Queue:
    # 初始化空队列
    def __init__(self):
        head = Node(0)
        self.front = head
        self.rear = head
    
    # 判断队列是否为空
    def is_empty(self):
        return self.front == self.rear
    
    # 入队操作
    def enqueue(self, value):
        node = Node(value)
        self.rear.next = node
        self.rear = node
    
    # 出队操作
    def dequeue(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            node = self.front.next
            self.front.next = node.next
            if self.rear == node:
                self.rear = self.front
            value = node.value
            del node
            return value
            
    # 获取队头元素
    def front_value(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            return self.front.next.value
        
    # 获取队尾元素
    def rear_value(self):
        if self.is_empty():
            raise Exception('Queue is empty')
        else:
            return self.rear.value

3. 队列的应用

队列是算法和程序中最常用的辅助结构,其应用十分广泛。比如现实生活中的排队买票、银行办理业务挂号等等。队列在计算机科学领域的应用主要提现在以下两个方面:

  1. 解决计算机的主机与外部设备之间速度不匹配的问题。
    • 比如解决主机与打印机之间速度不匹配问题。主机输出数据给计算机打印,输出数据的速度比打印数据的速度要快很多,如果直接把数据送给打印机进行打印,由于速度不匹配,显然行不通。为此,可以设置一个打印数据缓存队列,将要打印的数据依次写入缓存队列中。然后打印机从缓冲区中按照先进先出的原则依次取出数据并且打印。这样即保证了打印数据的正确,又提高了主机的效率。
  2. 解决由于多用户引起的系统资源竞争的问题。
    • 比如说一个带有多终端的计算机系统,当有多个用户需要各自运行各自的程序时,就分别通过终端向操作系统提出占用 CPU 的请求。操作系统通常按照每个请求在时间上的先后顺序将它们排成一个队列,每次把 CPU 分配给队头请求的用户使用;当相应的程序运行结束或用完规定的时间间隔之后,将其退出队列,再把 CPU 分配给新的队头请求的用户使用。这样既能满足多用户的请求,又能使 CPU 正常运行。
    • 再比如 Linux 中的环形缓存、高性能队列 Disruptor,都用到了循环并发队列。iOS 多线程中的 GCD、NSOperationQueue 都用到了队列结构。

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

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

相关文章

nginx使用与配置文件

nginx服务配置与配置优化 nginx服务脚本配置 mkdir wwwroot cd wwwroot/ mkdir nginx1 touch index.php vim index.php<?php echo $_SERVER["REMOTE_ADDR"]; ​ ​ vim conf/nginx.confserver {listen 80;server_name localhost;root /www/wwwroot/nginx…

分布式之SleuthZipkin

Sleuth&Zipkin 学习当前课程&#xff0c;比必须要先掌握SpringCloud的基本应用&#xff08;Nacos&#xff0c;Feign调用&#xff09; 对Docker有一定的了解&#xff0c;知道docker-compose.yml如何启动一个容器 RabbitMQ&#xff0c;Elasticsearch有一定了解。 而且学习…

SQLiteC/C++接口详细介绍sqlite3_stmt类(五)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍sqlite3_stmt类&#xff08;四&#xff09;- 下一篇&#xff1a; 无 12. sqlite3_bind_text16函数 sqlite3_bind_text16函数用于将UTF-16编码的文本数据&#xff08;字符串&#xff09;绑定…

HTML,子元素使用float后,导致父元素高度塌陷

HTML学习中遇到的一个任务&#xff1a;header 标签有两个元素 div&#xff08;标题&#xff09; 和 nav&#xff08;导航&#xff09;&#xff0c;希望实现的效果是标题在左侧&#xff0c;导航在右侧。 基础代码如下&#xff1a; <!DOCTYPE html> <html><head&…

辐射展—2024深圳辐射监测与防护展览会

2024深圳辐射监测与防护展览会 展会时间&#xff1a;2024年5月15-17日 展会地点&#xff1a;深圳国际会展中心&#xff08;宝安&#xff09; 主办单位&#xff1a;广东省辐射防护协会 广东省环境监测协会 深圳中国环境监测总站技术创新研究院&#xff08;福田&#xff09;…

mysql未完成事务查看

因为MySQL的事务管理主要是基于InnoDB存储引擎的&#xff0c;并且事务的状态&#xff08;例如&#xff0c;是否已提交或回滚&#xff09;通常是内部的、不直接暴露给用户的,但是可以通过一些方法间接地检查或诊断与事务相关的问题 查看正在运行的事务 使用SHOW ENGINE INNODB…

Flink RocksDB状态后端优化总结

截至当前&#xff0c;Flink 作业的状态后端仍然只有 Memory、FileSystem 和 RocksDB 三种可选&#xff0c;且 RocksDB 是状态数据量较大&#xff08;GB 到 TB 级别&#xff09;时的唯一选择。RocksDB 的性能发挥非常仰赖调优&#xff0c;如果全部采用默认配置&#xff0c;读写性…

小程序应用市场的前世今生

最开始的开始&#xff0c;为软件开发者提供软件发布、运营和推广服务的平台称之为软件应用市场&#xff0c;其发展经历了以下3个阶段&#xff1a; 起源阶段&#xff1a;应用市场的起源可以追溯到桌面互联网时代&#xff0c;当时软件的开发和分发主要依靠软件网站。软件开发者可…

【每日一题】 2024年2月汇编(下)

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 【2.16】103.二叉树的锯齿形层序遍历 103. 二叉树的锯齿形层序遍历https://leetcode.cn/problems/binary-tree-zigzag-level-or…

python课后习题一

题目&#xff1a; 1. 2. 解题过程&#xff1a; 1. """计算年数和天数""" minute int(input("请输入分钟数&#xff1a;")) hours minute // 60 days hours // 24 years days // 365 last_days days % 365 print(f"{minut…

Sora后时代文生视频的探索

一、写在前面 按常理&#xff0c;这里应该长篇大论地介绍一下Sora发布对各行业各方面产生的影响。不过&#xff0c;这类文章已经很多了&#xff0c;我们今天主要聊聊那些已经成熟的解决方案、那些已经可以“信手拈来”的成果&#xff0c;并以此为基础&#xff0c;看看Sora发布…

ArcGIS Pro与R:携手优化生态系统服务评估流程

生态系统服务是指生态系统所形成的用于维持人类赖以生存和发展的自然环境条件与效用&#xff0c;是人类直接或间接从生态系统中得到的各种惠益。联合国千年生态系统评估&#xff08;Millennium ecosystem assessment&#xff0c;MA&#xff09;提出生态系统服务包括供给、调节、…

【动态三维重建】Deformable 3D Gaussians 可变形3D GS用于单目动态场景重建(CVPR 2024)

主页&#xff1a;https://ingra14m.github.io/Deformable-Gaussians/ 代码&#xff1a;https://github.com/ingra14m/Deformable-3D-Gaussians 论文&#xff1a;https://arxiv.org/abs/2309.13101 文章目录 摘要一、前言二、相关工作2.1 动态场景的神经渲染2.2 神经渲染加速 三…

mac硬盘拷贝到另外硬盘 苹果电脑怎么拷贝到移动硬盘

在当今的信息时代&#xff0c;数据的存储和传输是我们日常生活和工作中不可或缺的一部分。我们经常需要使用各种硬盘来保存和备份我们的数据&#xff0c;比如内置硬盘、移动硬盘、U盘等。但是&#xff0c;不同的硬盘可能使用不同的文件系统&#xff0c;这给我们的数据拷贝带来了…

java 数据结构 排序算法

目录 排序 插入排序 直接插入排序 希尔排序( 缩小增量排序 )&#xff1a; 直接选择排序 堆排序 交换排序 冒泡排序 快速排序递归 Hoare法 挖坑法 前后指针法 快速排序优化 快速排序非递归 归并排序 归并排序非递归 排序算法复杂度及稳定性分析 计数排序 排序…

【论文阅读】Masked Autoencoders Are Scalable Vision Learners

Masked Autoencoders Are Scalable Vision Learners 引用&#xff1a; He K, Chen X, Xie S, et al. Masked autoencoders are scalable vision learners[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition. 2022: 16000-16009. 论文链…

wireshark抓tcp包使用指南

本博文源于笔者不断探索加上去网络总结获得的经验&#xff0c;撰写wireshark如何抓tcp包 文章目录 1、打开wireshark2、选择网络源3、搜索ip地址与tcp条件4、看灰色的条纹 1、打开wireshark 2、选择网络源 选择自己当前的ip地址适用于的网络源&#xff0c;比如这里选择“以太…

ETH Gas 之 Base Fee Priority Fee

前情回顾 ETH网络 之 Gas EIP-1559 EIP-1559 EIP-1559是以太坊改进提案&#xff08;Ethereum Improvement Proposal&#xff09;&#xff0c;旨在改进以太坊的交易费用机制。该提案引入了一种新的交易费用模型&#xff0c;以提高交易费用的可预测性和网络的效率。我们本文各…

故障诊断 | 一文解决,GRNN广义回归神经网络的故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍模型描述源码设计参考资料效果一览 文章概述 故障诊断 | 一文解决,GRNN广义回归神经网络的故障诊断(Matlab) 专栏介绍

拥抱DevOps,开启数字化转型的加速器

在数字化浪潮席卷全球的今天&#xff0c;企业面临着前所未有的挑战与机遇。为了保持竞争力并适应快速变化的市场需求&#xff0c;数字化转型已成为企业发展的必由之路。而在这一过程中&#xff0c;DevOps作为一种全新的开发与运维理念&#xff0c;正逐渐成为推动企业数字化转型…
最新文章