Author: doyo
队列(queue) 是一种特殊的线性表,它仅允许在一端进行插入,在另一端进行删除。允许删除的这一端称为队头 或者队首,允许插入的那一端称为队尾。
生活中一个典型的例子就是食堂打饭时的排队。食堂师傅将优先给队头的同学打饭,并让他出队;后来的同学则只能从队尾入队等待。
仔细观察,我们可以发现,队列中的元素具有“先入队的先出队,后入队的后出队”的特性。我们称这种特性为先进先出(First-In-First-Out,FIFO)。
下面基于上上份讲义中的单向链表给出栈的一种实现。正如前文所述,队列实际上也是一种特殊的线性表,所以只需要对单向列表的实现略作修改,使其插入仅在其一端、删除在另一端进行即可。
完整代码详见此处(点击下载)。
跟单向列表和栈都是一样的;
typedef int ElemType;
struct node {
ElemType data;
struct node *next;
};
稍微不一样的是队列需要两个指针,一个指向队首,一个指向队尾:
struct node *QueueHead, *QueueTail;
类似于访问栈顶元素:
ElemType Front() {
if (QueueHead == NULL) {
printf("Error: The queue is empty!\n");
ErrorFlag = true;
return -1;
} else {
return QueueHead->data;
}
}
// 你可能觉得上面这段代码看着有点眼熟
// 没错,我就是从栈那里复制过来的,只是修改了变量名(以及函数名)而已
与栈不同的是,新元素入队时,是从队尾入队。
void Push(ElemType data) {
ErrorFlag = false;
struct node * ptr = NewSpace;
ptr->data = data;
ptr->next = NULL;
if (QueueHead == NULL) {
QueueHead = QueueTail = ptr; // 注意如果队列本来是空的,要把队头也指向新元素
} else {
QueueTail->next = ptr; // 由于是从队尾入队,所以注意指针的指向
QueueTail = ptr;
}
}
与弹栈的操作类似,但是是从队首进行:
ElemType Pop() {
if (QueueHead == NULL) {
printf("Error: The queue is empty!\n");
ErrorFlag = true;
return -1;
} else {
struct node * ptr = QueueHead;
ElemType data = ptr->data;
QueueHead = QueueHead->next;
free(ptr);
return data;
}
}
不仅仅是栈可以用数组实现,队列也是可以的。请参考这篇讲义。