队列-知识点

队列

队列是一种特殊线性表,与栈相同。队列的插入和删除操作分别在两端进行,与栈不相同,因此队列是一个先进先出的线性表。

定义

队列是一个线性表,其插入和删除操作分别在表的不同端进行。插入元素的那一端称为队尾(back 或 rear),删除元素的那一端称为队首(front)

记忆队列时,可以联想我们平时排队的情形。在排队的过程中遵守先来先到原则,也即是先进先出原则。

抽象数据类型(ADT)

在队列当中,常见的操作有如下:

functions runtimes description
q.dequeue() O(1) removes front value and returns it;throws error if queue is empty
q.enqueue(value) O(1) places given value at back of queue
q.isEmpty() O(1) returns true of queue has no elements
q.peek() O(1) returns front value without removing;throws an error if queue is empty
q.size() O(1) return number of elements in queue

数组实现

若要通过数组来实现队列,首先需要考虑将哪端作为队首,哪端作为队尾。

  • 假如将 index = 0 作为队首,即 location(i) = i;

队列的第 i 个元素存储在 queue[i] 中,queueFront = 0,队列长度 = queueBack + 1,在队列空时,queueBack = -1。

当进行插入操作时,所需要的时间 Θ(1)(queueBack 加1,再把元素插入到 queue[queueBack]当中),当进行删除操作时,所需要的时间是 Θ(n),其中 n 为删除之后剩余元素的个数。

  • 假如队首位置不固定时,即 location(i) = location(队首元素) + i

此时,删除操作所需要的时间将减少至 Θ(1)。

然而,当这样使用数组时,可能会出现许多未使用空间,且数组长度已经被扩大数倍。这个时候我们可以将数组视为一个环(将数组视为环是为了理解,其实是对下标进行设置),就可以利用这些空余空间,同时插入和删除的最坏时间复杂度都会变成 Θ(1) ,

这也被称为循环队列

循环队列

对于循环队列,也有两种实现方式:

当然,无论以何种方式进行实现,队列元素的个数最多是 $arrayLength - 1$ 。

void Initqueue (SqQueue *&q) 
{  
   q=(SqQueue *)malloc(sizeof(SqQueue));
   q->rear = q->front = 0;
}

bool QueueEmpty (SqQueue *q ) 
{
    if ( q->rear == q->front)  return true;
    else	return false;
}
bool enQueue (SqQueue *&q, elemtype e ) 
{
    if ( q->front= =(q->rear+1)% maxsize )
          return false;
    q->rear = ( q->rear+1) % maxsize;
    q->data[q->rear] = e;
    return true;
}
bool deQueue (SqQueue *q; elemtype &e ) 
{
    if ( q->front==q->rear)
          return false;		
    q->front = ( q->front+1) % maxsize;
    e = q->data[q->front];
    return true;
}

链表实现

同理,在使用链表对队列进行实现过程中,需要考虑头的位置。在链表中,则是考虑指针的方向。1. 指针由头指向尾,2. 指针由尾指向头。

对于这两种方式,插入操作均没有差别,而对于删除操作,第一种方式会更加方便,因此我们通常采用从头至尾的链接方向。

操作如下:(贴图就对了)

优先队列

优先队列是一种特殊的队列,在优先队列中,其中的元素被赋予了不同的权值大小,代表了各个元素的优先级。

可能会存在的操作如下:

actions description
pq.enqueue(value, pri) adds value to queue,with the given priority number
pq.dequeue() return the value in the queue with most urgent(minimum)priority;thros an error if empty
pq.peekPriority() returns priority of most urgent priority element;throws error if queue is empty
pq.isEmpty() return true if queue contains no elements(size 0)
pq.size() returns the number of elements in the queue
out « pq return / print a string such as “{3, 42, -7, 15}”
pq.changePriority(value, pri) alters an existing element’s priority to be more urgent
pq.clear() removes all elements of the queue
pq.peek() returns most urgent priority element without removing it;throws error if queue is empty

实际应用

(暂略。累了去休息了