Perl 实现一个队列

Perl 实现一个队列

Perl中的 队列 是一种线性的抽象数据结构,它遵循 先进先出 的顺序。它类似于我们在日常生活中遇到的队列的特性,即谁先来谁就先得到服务。它在两端都是开放的。与堆栈不同的是,插入和删除的操作发生在被称为堆栈 顶部 的同一端,在队列中,这些操作发生在被称为队列 前端 端的不同一端。

对队列的操作

以下是对队列的基本操作。

  1. Enqueue(插入): 向队列中添加一个项目。如果队列满了,会出现 溢出 条件。
  2. Dequeue(删除): 从队列中删除一个项目。如果队列是空的,会发生 下溢 条件。
  3. Front(前): 从队列中获取前面的项目。
  4. rear: 从队列中获取最后一个项目。

Perl  实现一个队列

创建一个队列

在Perl中创建一个队列非常简单。它可以通过声明一个数组来完成,这个数组可以是空的,也可以用一些预先填充的数据进行初始化。

@queue;        # Queue is empty.

@queue = (1, 2, 3);      # Queue with initialized values.

队列的类型

根据插入和删除的标准,队列可以有以下类型。

简单队列

简单队列是一个简单的队列,插入发生在队列的前端,删除发生在队列的末端。
在Perl中,队列的操作可以用 pushshift 函数来实现。
push 函数用来在队列的末端添加一个或多个值。
shift 函数将队列向左移动一个单位,删除(弹出)第一个元素。在队列为空的情况下,它将返回 undef

例子

#!/usr/bin/perl
use strict;
use warnings;
   
# Intitialising the Queue
my @queue = (1, 2, 3);
   
# Original queue
print "Original Queue: @queue";
 
# Pushing values into queue
push(@queue, (4, 5, 6)); 
   
# Updated Queue after 
# Push operation
print("\nUpdated Queue after Push: @queue");
 
 
# Popping values from queue
my val1 = shift(@queue);
print("\nElement popped is:val1");
my val2 = shift(@queue);
print("\nElement popped is:val2"); 
   
# Updated Queue after 
# Pop operations
print("\nUpdated Queue after Pop: @queue");

输出

Original Queue: 1 2 3
Updated Queue after Push: 1 2 3 4 5 6
Element popped is: 1
Element popped is: 2
Updated Queue after Pop: 3 4 5 6

循环队列

在圆形队列中,队列的最后一个位置与第一个位置相连,形成一个圆形,也被称为 环形缓冲区。 如果队列的前端是空的,但末端是满的,那么我们也可以在循环队列中插入元素,这在简单队列中是不存在的。圆形队列的 大小是固定的 ,与普通队列不同。
除了 pushshift 函数外,圆形队列还有两个变量 frontrearrow 来存储队列的前部和后部位置。

Perl  实现一个队列

例子

#!/usr/bin/perl
use strict;
use warnings;
 
# Intitialising the Queue
my @queue = (1, 2, 3);
my size = 7; # No. of elements to be stored in queue
 
# Initially queue has three elements
myfront = 0;
my rear = 2;
 
# Original queue
print "Original Queue: @queue";
 
# Pushing values into queuerear = (rear + 1) %size;
my val = 4;
while(1)
{
    if (rear == front)
    {
        print("\nQueue is full.");
        last;
    }
    else
    {
        print("\nPushedval in queue");
        queue[rear] = val;
        rear = (rear + 1) %size;
        val += 1;
    }
}
 
# Updated Queue after
# Push operation
print("\nUpdated Queue after Push: @queue");
 
# Popping values from queue
myval1 = queue[front];
queue[front] = -1;
front = (front + 1) % size;
print("\nElement popped is:val1");
 
my val2 =queue[front];queue[front] = -1;front = (front + 1) %size;
print("\nElement popped is: val2");
 
# Updated Queue after
# Pop operations
print("\nUpdated Queue after Pop: @queue");
while(1)
{
    if (rear % size ==front)
    {
        print("\nQueue is full.");
        last;
    }
    else
    {
        print("\nPushed val in queue");
        queue[rear] =val;
        rear += 1;
        val += 1;
    }
}
print("\nUpdated Queue after Push: @queue");

输出

Original Queue: 1 2 3
Pushed 4 in queue
Pushed 5 in queue
Pushed 6 in queue
Pushed 7 in queue
Queue is full.
Updated Queue after Push: 1 2 3 4 5 6 7
Element popped is: 1
Element popped is: 2
Updated Queue after Pop: -1 -1 3 4 5 6 7
Pushed 8 in queue
Pushed 9 in queue
Queue is full.
Updated Queue after Push: 8 9 3 4 5 6 7

优先级队列

在优先级队列中,每个项目都有一个定义的 优先级 与之相关。优先级最低的项目将首先被从优先级队列中删除。具有相同优先级的项目将按照它们在队列中的顺序进行处理,

例子

#!/usr/bin/perl
use strict;
use warnings;
 
# Initialising queue with priority
my @queue = ([1, 3], [2, 7], [4, 3], [5, 2]);
 
sub pull_highest_prio
{
    my max = 0;
    for (myi = 0; ii++)
    {
        if (queue[i][1] > queue[max][1])
        {
            max =i;
        }
    }
    print("\nPopped item: queue[max][0], ",
          "Priority: queue[max][1]");
    splice @queue, max, 1;
}
 
# Driver Code
print("\nOriginal Queue is ");
for (myi = 0; i<4;i++)
{
    print("queue[i][0] ");
}
push(@queue, [11, 9]);
push(@queue, [7, 0]);
 
print("\nUpdated Queue after push is ");
for (my i = 0;i < 6; i++)
{
    print("queue[i][0] ");
}
pull_highest_prio;
pull_highest_prio;
pull_highest_prio;
pull_highest_prio;
 
print("\nUpdated Queue after pop is ");
for (myi = 0; i<2;i++)
{
    print("queue[i][0] ");
}

输出

Original Queue is 1 2 4 5 
Updated Queue after push is 1 2 4 5 11 7 
Popped item: 11, Priority: 9
Popped item: 2, Priority: 7
Popped item: 1, Priority: 3
Popped item: 4, Priority: 3
Updated Queue after pop is 5 7

Deque(Doubly Ended Queue)

双端队列只是简单队列的一个通用版本,除了插入和删除操作,可以在队列的 前端后端 都进行。它是一种非常重要的数据结构类型,因为它既可以作为堆栈也可以作为队列使用。

例子

#!/usr/bin/perl
use strict;
use warnings;
 
# Intitialising the Queue
my @queue = (1, 2, 3);
my front = 0;
myrear = 2;
sub insert_front
{
    my val =_[0];
    unshift(@queue, val);
    rear += 1;
}
 
sub insert_rear
{
    my val =_[0];
    push(@queue, val);
    rear += 1;
}
 
sub delete_front
{
    print("\nElement popped is: queue[0]");
    splice @queue, 0, 1;
    rear -= 1;
}
 
sub delete_rear
{
    print("\nElement popped is: queue[rear]");
    splice @queue, scalar(@queue) - 1, 1;
    rear -= 1;
}
 
# Original queue
print "Original Queue: @queue";
 
# Pushing values into queue
&insert_rear(4);
&insert_rear(3);
print("\nRear element isqueue[rear]");
&insert_front(1);
&insert_front(7);
print("\nFront element isqueue[front]");
 
# Updated Queue after
# Push operation
print("\nUpdated Queue after Push: @queue");
 
# Popping values from queue
delete_rear;
delete_front;
print("\nFront element isqueue[front]");
 
&insert_front(20);
delete_rear;
print("\nRear element isqueue[$rear]");
 
# Updated Queue after
# Pop operations
print("\nUpdated Queue after Pop: @queue");

输出

Original Queue: 1 2 3
Rear element is 3
Front element is 7
Updated Queue after Push: 7 1 1 2 3 4 3
Element popped is: 3
Element popped is: 7
Front element is 1
Element popped is: 4
Rear element is 3
Updated Queue after Pop: 20 1 1 2 3

抽象实现

在Perl中,队列的抽象实现可以通过Perl的内置模块 Thread::Queue 来实现,它提供了线程安全的FIFO队列,可以被任意数量的线程访问。

基本方法

  1. new(list) – 用提供的项目列表创建一个新队列,如果没有列出,则创建一个新的空队列。
  2. enqueue(list) – 在队列的末端添加一个项目列表。
  3. dequeue(COUNT) – 从队列头部移除所要求的项目数量,并返回它们,如果没有提到,它从队列中取消一个元素。
  4. pending() – 返回队列中还剩下的项目数,或者我们可以说,它基本上返回队列的大小。
  5. end() – 声明不再有项目被添加到队列中。

例子

#!/usr/bin/perl
use strict;
use warnings;
 
use Thread::Queue;
 
# A new pre-populated queue
my q = Thread::Queue->new(1, 2, 3);    
 
sub head
{
    if (q->pending() == 0)
    {
        print("\nThe queue is empty.");
    }
    else
    {
        my item =q->dequeue();
        print("\nHead of the Queue is item.");
    }
}
myisize = q->pending();
print("Initial size of the queue isisize");
 
# insert three items at the back of the queue
q->enqueue(5, 6, 7);    
&head();
 
mysize = q->pending();
print("\nThe size of the queue issize");
 
# delete the head item of the queue
q->dequeue();            
&head();
 
# delete two items from the frontq->dequeue(2);        
my size2 =q->pending();
print"\nThe size of the queue is size2";
 
&head();
&head();q->end();

输出

 size of the queue is 3
Head of the Queue is 1.
The size of the queue is 5
Head of the Queue is 3.
The size of the queue is 1
Head of the Queue is 7.
The queue is empty.

平行或异步处理

并行 的意思是同时或在同一时间,而 异步 的意思是连续或无阻塞的。队列的执行操作是阻塞的,即在执行一个操作时,其他操作必须先等待它结束,然后再执行。这对于少量的任务来说是没有问题的,但是对于大量的任务或操作来说,这种处理方式就显得有点忙乱和费时了。
为了克服这个问题,Perl提供了一些进行并行或异步处理的方法,这样这些操作就可以同时运行或不需要等待其他操作结束。这方面的两个主要解决方案是 线程分叉。 分叉是指创建完全相同的某个进程的副本,然后这两个进程平行地执行,尽管它们操作或处理相同的变量(副本),但它们的变量之间没有什么联系。这是用 fork() 函数完成的。

例子

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
      
say "PID $";
mypid = fork();
die if not defined pid;
say "PID(pid)";

输出

PID 22112
PID 22112 (22113)
PID 22113 (0)

在调用 fork() 之前,我们得到了一个PID(22112),这是当前进程的进程ID,在分叉之后,我们得到了两行。第一行是来自与当前进程相同的进程(它有相同的PID),第二行是来自子进程(PID为63779)。第一行从fork收到一个$pid,包含子进程的编号。第二个,子进程得到的数字是0。
Perl也通过POE框架支持事件驱动的编程。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程