数据结构中的 FIFO 方法

2025年3月17日 | 阅读32分钟

FIFO 的全称是 先进先出,在这种方法中,我们将数据元素输入到数据结构中;最后添加到任何数据结构中的数据元素将最后被移除,而首先添加的元素将首先被移除。在这里,我们平等对待数据元素;首先进入的元素将首先有机会离开。我们称之为先来先服务,它是通过一种名为队列的数据结构实现的。

理解 FIFO 原理的最佳示例是排队购买电影票,前面有很多人,我们别无选择,只能等待。如果我们观察上面的例子,我们可以清楚地看到,我们将排在前面的人之后,并被视为先来先服务。

  • FIFO 原理在各种进程调度算法中具有重要意义,操作系统使用这些算法来确定多个进程的调度顺序。
  • CPU 使用的算法之一是 FCFS(先来先服务),它为每个进程提供公平的机会,并且通过使用队列数据结构来实现。
  • 在最早的调度算法之一中,我们将使用循环算法,而循环队列具有重要意义;通过使用循环队列,我们可以抢占进程,并使用循环队列为每个进程提供公平的机会。该算法由计算中的进程和网络调度程序使用。
  • 它也用于计算机控制的交通信号系统
  • 它也用于 CPU 调度和内存管理。
  • 基于 FIFO 原理的数据结构是队列。
  • 在队列数据结构中,我们将执行两个主要操作:首先,Enqueue 操作用于将数据元素插入队列;另一个是 Dequeue 操作,用于从队列中移除数据元素。
  • 在栈中,我们主要使用两个操作:push 用于将数据元素压入栈,另一个是 pop 用于从栈中移除元素。
  • 队列有两个端,即队首队尾
  • 许多程序都基于 FIFO 原理的概念。
  • 队列是一种重要的线性数据结构,广泛用于各种计算机应用程序,并且它基于FIFO(先进先出)原理。它遵循特定的数据执行顺序来进行操作。在此数据结构中,数据从一端(即队尾)进入,下一个数据在前面的数据之后进入队列。删除操作从另一端(即队首)执行。
  • 与栈相比,栈也是一种线性数据结构。虽然它基于LIFO(后进先出)原理,这意味着数据一次从一端进入栈,直到达到其末端限制,然后数据元素从同一端弹出。
  • 在栈中,只需要一个指针来执行所有操作,即栈顶;而在队列中,需要两个指针,即队尾队首,来执行所有操作。

如前所述,这种方法称为先进先出方法或 FIFO。

FIFO 方法的应用

FIFO 的应用如下:

1)数据结构

队列是一种基于 FIFO 方法的线性数据结构,其中数据元素通过队尾进入队列,并通过队首删除元素。

FIFO 方法主要用于网络桥接器、交换机路由器

它进一步被归类为线性队列。

线性队列

线性队列是一种基于 FIFO(先进先出)原理的线性数据结构,其中数据从队尾进入,从队首删除。线性队列被认为是简单队列,当我们讨论队列时,默认是指线性队列。我们将在后面的部分更详细地讨论这些端点。

其他示例,如 ->

  • 人们在等公交车。排在队列前面的人将是第一个上车的人。
  • 汽车排在收费站桥前。最先到达桥的汽车将是第一个离开的。

线性队列的操作

线性队列中有一些基本操作如下 ->

  1. 入队
    • 此操作用于向队列添加数据元素。
    • 通过应用此操作,数据按顺序一个接一个地进入队列。入队操作将一直持续,直到队列达到其末端限制。
    • 一旦达到终点,就无法将数据添加到队列中,此时称为溢出条件。
    • 入队操作从队尾执行。
  2. 出队
    • 此操作用于从队列中删除数据元素。
    • 使用出队操作,删除的是最先入队的那个数据元素,或者元素按入栈的相同顺序出栈。
    • 此过程将删除队列中的数据元素,直到整个队列变空。一旦所有元素都被删除,则无法执行删除操作,此时称为下溢条件。
    • 它从队首执行。
  3. 查看
    此操作用于在不将其出队的情况下,找出最先要服务的队列元素。

线性队列的两个端

  1. 队首 - 指队列的初始或起始位置。队首主要用于从队列中删除数据元素或执行出队操作。
  2. 队尾 - 指队列的最后或后部位置。队尾主要用于插入队列数据元素或执行入队操作。

线性队列的实现方法

有各种实现队列的方法。

  • 使用数组实现队列
  • 使用栈实现队列
  • 使用链表实现队列

使用数组实现线性队列

这里我们讨论使用数组实现队列 ->

队列可以很容易地通过使用线性数组来实现。如前所述,队列有队首和队尾指针,可以从中删除和插入数据元素。

步骤:

  1. 最初,我们需要创建一个大小为“n”的数组,无论是静态的还是动态的,取决于用户。
  2. 声明两个指针,分别称为 FRONT 和 REAR。
  3. 将 REAR 初始化为 -1,FRONT 初始化为 0。
  4. 创建三个函数,分别称为 Enqueue(用于向队列添加数据元素)、Dequeue(用于从队列删除数据元素)和 peek(用于在不将其出队的情况下找出队列的第一个元素)。
FIFO Approach in data structure

入队操作算法

步骤 1 - 检查 REAR == FRONT。

步骤 2 - 如果上述语句成立,则称这种情况为溢出,无法进一步插入数据元素。

步骤 3 - 如果不成立,则

  • 将 REAR = REAR + 1,然后
  • 在队尾位置将数据元素添加到队列中。
  • Queue[REAR] = data。

出队操作算法

步骤 1 - 检查 FRONT = REAR + 1。

步骤 2 - 如果上述语句成立,则

  • 这种情况称为下溢。
  • 返回 -1。

步骤 3 - 如果不成立,则

  • 从队列的队首位置弹出值。
  • data = Queue[FRONT]。
  • 返回数据。

步骤 4 - 然后设置 FRONT = FRONT + 1,它指向下一个数据元素。

Peek 操作算法

步骤 1 - 检查 FRONT = REAR + 1。

步骤 2 - 如果上述语句成立,则显示消息;队列为空。

步骤 3 - 如果不成立,则

  • 返回队列中位于队首位置的数据元素。
  • data = Queue[FRONT]。
  • 返回数据。

使用队列(数组实现)在 C 编程语言中实现 FIFO 方法

上述程序的输出是

FIFO Approach in data structure

使用数组(队列实现)在 C++ 编程语言中实现 FIFO 方法

上述程序的输出是

FIFO Approach in data structure

使用队列在 Java 编程语言中实现 FIFO 方法

上述程序的输出是

Queue is Empty
 20 <--  30 <--  40 <--  50 <-- 
Queue is full
 20 <--  30 <--  40 <--  50 <-- 

after two node deletion

 40 <--  50 <-- 
Front Element is: 40

使用队列在 Python 编程语言中实现 FIFO 方法

上述程序的输出是

   Elements of queue - [ 0, 1, 2, 3, 4 ]
   removed element - 0
   [ 1, 2, 3, 4 ]
   Peek value of queue - 1
   Size of queue - 4

使用队列在 C# 编程语言中实现 FIFO 方法

上述程序的输出是

   Elements of queue - [ 0, 1, 2, 3, 4 ]
   removed element - 0
   [ 1, 2, 3, 4 ]
   Peek value of queue - 1
   Size of queue - 4

使用队列在 JavaScript 编程语言中实现 FIFO 方法

上述程序的输出是

   Elements of queue - [ 0, 1, 2, 3, 4 ]
   removed element - 0
   [ 1, 2, 3, 4 ]
   Peek value of queue - 1
   Size of queue - 4

使用栈(队列实现)在 C 编程语言中实现 FIFO 方法

上述程序的输出是

  Queue is empty !!
  Queue is full !!
  20
  30
  40
  50

使用栈(队列实现)在 C++ 编程语言中实现 FIFO 方法

上述程序的输出是

Queue is empty !!
  Queue is full !!
  20
  3
  40
  50

循环队列

使用循环队列实现 FIFO 方法

循环队列也是一种重要的队列类型。它与线性队列相似,但有一些变体。循环队列的末端位置连接回起始位置,形成类似圆形的结构并构成一个圆。循环队列也基于先进先出(FIFO)原理。它也称为“环形缓冲区”

正如我们之前所见,在线性队列中,当 REAR 到达末端且 FRONT 也到达末端时,无法进一步插入数据元素。队列仍然为空,但它显示队列已满,因此引入了循环的概念来解决上述问题。在循环队列中,此问题不会出现。我们将在下面的部分中进一步详细讨论。

基于 FIFO 原理的数据结构是栈。我们主要对其进行两种操作:pushpop。Push 操作用于将数据元素压入栈,pop 操作用于从栈中弹出数据元素。

线性队列中有一些基本操作如下 ->

  1. 入队
    • 此操作用于向队列插入数据元素。
    • 在循环队列中,数据元素始终从队尾位置添加。
  2. 出队
    • 此操作用于从队列中删除数据元素。
    • 在循环队列中,数据元素的删除始终从队首位置进行。

循环队列的两个端

在循环队列中,有一个类似圆形的结构;因此没有两个端点区分开,但为了区分数据元素的插入和删除标准,我们仍然引用这两个端点。

  1. 队首 - 用于从队列中删除数据元素。
  2. 队尾 用于向队列中插入数据元素。

使用数组实现循环队列

循环队列可以很容易地通过使用数组来实现。它基于循环增量过程。如前所述,它有两个指针,队首和队尾。从队尾可以插入数据元素。如果队尾指针到达末端,它会再次递增到队列的初始位置,以便还可以进行进一步插入,因此这表示一个增量过程。

从队首可以删除数据元素。如果队首指针到达末端,它会返回到队列的初始位置,以便可以进行进一步删除。

使用队列大小的模运算执行循环增量。

步骤:

  1. 最初,我们需要创建一个大小为“n”的数组,无论是静态的还是动态的,取决于用户。
  2. 然后声明两个指针,分别称为 FRONT 和 REAR。
  3. 将 REAR 初始化为 -1,FRONT 初始化为 -1。
  4. 创建两个函数,分别称为 Enqueue(用于向队列添加数据元素)和 Dequeue(用于从队列删除数据元素)。
FIFO Approach in data structure

循环队列的实现

入队操作算法

步骤 1 - 检查 FRONT == 0 && REAR == (n-1) || REAR == (FRONT - 1) % (n-1)。

步骤 2 - 如果上述语句成立,则称这种情况为溢出,无法进一步插入数据元素。

步骤 3 - 否则,如果 FRONT == -1,则

  • 设置 REAR = 0,FRONT = 0,然后
  • 在队尾位置将数据元素添加到队列中。
  • Queue[REAR] = data。

步骤 4 - 否则,如果 REAR == (n-1) && FRONT != 0

  • 设置 REAR = 0,然后
  • 在队尾位置将数据元素添加到队列中。
  • Queue[REAR] = data。

步骤 5 - 否则

  • 设置 REAR = REAR + 1
  • 在队尾位置将数据元素添加到队列中。
  • Queue[REAR] = data。

出队操作算法

步骤 1 - 检查 FRONT == -1。

步骤 2 - 如果上述语句成立,则

  • 这种情况称为下溢。
  • 返回 -1。

步骤 3 - 如果不成立,则

  • 从队列的队首位置弹出值。
  • data = Queue[FRONT]。
  • 返回数据。

步骤 4 - 然后设置 FRONT = FRONT + 1,它指向下一个数据元素。

步骤 5 - 如果 FRONT == REAR,则设置 FRONT = -1 和 REAR = -1。

步骤 6 - 否则,如果 FRONT == n-1,则设置 FRONT = 0。

使用循环队列在 C 编程语言中实现 FIFO 方法

上述程序的输出是

 Enqueue value 20 successfully !!
 Enqueue value 30 successfully !!
 Enqueue value 40 successfully !!
 Enqueue value 60 successfully !!
 Enqueue value 70 successfully !!
 Queue is full !!
 Deleting  value: 20
 Deleting  value: 30
 Deleting  value: 40
 Deleting  value: 60

使用结构(循环队列实现)在 C++ 编程语言中实现 FIFO 方法

上述程序的输出是

Enqueue value 7 successfully !!
 Enqueue value 11 successfully !!
 Enqueue value 4 successfully !!
 Enqueue value 6 successfully !!
 Enqueue value 7 successfully !!
 Queue is full !!
 Deleting  value: 7
 Deleting  value: 11
 Deleting  value: 4
 Deleting  value: 6

使用数组(循环队列)在 Java 编程语言中实现 FIFO 方法

上述程序的输出是

Elements in Circular Queue are : 14   22  13   8
Deleted value = 14    
Deleted value = 22    
Elements in Circular Queue are : 13  8
Elements in Circular Queue are :  13  8   9   20   5
Queue is Full !!

使用数组(循环队列)在 Python 编程语言中实现 FIFO 方法

上述程序的输出是

Elements in Circular Queue are : 4   22   3   -6
Deleted value = 4    
Deleted value = 22    
Elements in Circular Queue are : 3  -6
Elements in Circular Queue are :  3  -6   19   2   15
Queue is Full !!

使用链表(循环队列)在 C 编程语言中实现 FIFO 方法

上述程序的输出是

Enqueue value is: 20
 Enqueue value is: 30
 Enqueue value is: 40
 Deleting  value: 20
 Deleting  value: 30
 Deleting  value: 40
 Queue is empty !!
 Enqueue value is: 60
 Enqueue value is: 50
 Enqueue value is: 70
  Queue is full !!

使用链表(循环队列)在 C++ 编程语言中实现 FIFO 方法

上述程序的输出是

Enqueue value is: 20
 Enqueue value is: 30
 Enqueue value is: 40
 Deleting  value: 20
 Deleting  value: 30
 Deleting  value: 40
 Queue is empty !!
 Enqueue value is: 60
 Enqueue value is: 50
 Enqueue value is: 70
  Queue is full !!

使用链表(循环队列)在 Java 编程语言中实现 FIFO 方法

上述程序的输出是

Elements in Circular Queue are : 10   2    16
Deleted value = 10    
Deleted value = 2    
Elements in Circular Queue are : 16
Elements in Circular Queue are : 16    19   7

使用链表(循环队列)在 Python 编程语言中实现 FIFO 方法

上述程序的输出是

Elements in Circular Queue are : 10   2    16
Deleted value = 10    
Deleted value = 2    
Elements in Circular Queue are : 16
Elements in Circular Queue are : 16    19   7

循环队列相对于线性队列的优点

  • 与循环队列相比,线性队列消耗更多内存。
  • 循环队列使用一种有效的方式进行内存利用。
  • 在循环队列中,在删除某个位置的先前数据后,可以再次在该位置插入新数据。
  • 在线性队列中,如果队尾指针到达最后,并且队首指针删除了队列中的所有数据,它仍然会显示溢出消息,这是线性队列的主要缺点。
  • 当队列已满时,循环队列会显示溢出消息。
  • 易于执行出队和入队操作。