一、队列的定义和基本操作
1、队列的定义
队列(queue)又名队,它是一种运算受限的线性表。
限定仅允许在一端进行插入,这一端被称为队头(front);在另一端进行删除操作的线性表,这一端被称为队尾(rear);
向队列中插入新元素又称作入队(EnQueue),它是把新元素放到队尾元素的上面,使之成为新的队尾元素;
从队列中删除元素称作出队(DeQueue),它是把队头元素删除掉,使其相邻的元素成为新的队头元素。
栈的操作特性为先进先出FIFO(First In First Out)
2、队列的基本操作
InitQueue(&Q):初始化一个空队列;
QueueEmpty(Q):判断一个队列是否为空,若队列Q为空则返回true,否则返回false;
EnQueue(&Q, x):入队,若队列Q未满,则将x加入使之成为新队尾;
DeQueue(&Q,&x):出队,若队列Q非空,则删除队头元素,并用x返回;
GetHead(Q,&x):读队头元素,若队列Q非空,则用x返回队头元素;
二、队列的存储方式及其实现
队列的存储方式主要有两种:
2.1顺序队列
即队列的顺序存储结构。利用一组地址连续的存储单元依次存放队列中的元素,并附设两个指针:队头指针front指向队头元素,队尾指针rear指向队尾元素的下一个位置。示意图如下:
元素入队时,rear向后移动;元素出队时,front向后移动;最终两个指针会达到数组末端处,此时会造成队列的“假溢出”。为了解决这一问题,使用循环队列代替顺序队列。
循环队列就是将顺序队列从逻辑上视为一个环,当队首指针Q.front=MaxSize-1后,再前进一个位置就自动到0。示意图如下:
队列的顺序存储结构可如下定义:
#define MaxSize 50 //定义队列中元素的最大个数
typedef struct{
Elemtype data[MaxSize]; //存放队列中元素
int front,rear; //队头指针、队尾指针
}SqQueue;
顺序栈的基本操作实现如下:
// 初始化队列
void InitQueue(SqQueue *q) {
q->front = q->rear = 0;
}
// 判断队列是否为空
int QueueEmpty(SqQueue q) {
return q.front == q.rear;
}
// 入队
int EnQueue(SqQueue *q, int x) {
// 判断队列是否已满
if ((q->rear + 1) % MAXSIZE == q->front) {
return 0;
}
q->data[q->rear] = x;
q->rear = (q->rear + 1) % MAXSIZE;
return 1;
}
// 出队
int DeQueue(SqQueue *q, int *x) {
// 判断队列是否为空
if (q->front == q->rear) {
return 0;
}
*x = q->data[q->front];
q->front = (q->front + 1) % MAXSIZE;
return 1;
}
2.2 链队列
即队列的链式存储结构。是一个同时带有队头指针和队尾指针的单链表,头指针指向队头结点,尾指针指向队尾结点。用单链表表示的链队列适合于数据元素变动比较大的情况,而且不存在队列满且产生溢出的问题。示意图如下:
队列的链式存储结构可如下定义:
// 链队列结构体定义
typedef struct QueueNode {
int data;
struct QueueNode* next;
} QueueNode;
typedef struct {
QueueNode* front; // 队头指针
QueueNode* rear; // 队尾指针
} LinkQueue;
链队列的基本操作实现如下:
// 初始化链队列
void InitQueue(LinkQueue* Q) {
Q->front = Q->rear = (QueueNode*)malloc(sizeof(QueueNode));
Q->front->next = NULL;
}
// 入队操作
void EnQueue(LinkQueue* Q, int x) {
QueueNode* s = (QueueNode*)malloc(sizeof(QueueNode));
s->data = x;
s->next = NULL;
Q->rear->next = s;
Q->rear = s;
}
// 出队操作
int DeQueue(LinkQueue* Q) {
if (Q->front == Q->rear) {
printf("队列为空!\n");
exit(-1);
}
QueueNode* p = Q->front->next;
int x = p->data;
Q->front->next = p->next;
if (Q->rear == p)
Q->rear = Q->front;
free(p);
return x;
}
// 判断队列是否为空
int IsEmpty(LinkQueue* Q) {
if (Q->front == Q->rear)
return 1;
else
return 0;
}
总结
本文仅仅简单介绍了队列的定义与基本实现,仅供参考。