队列
一. 队列的定义及基本运算
栈是一种后进先出的数据结构,在实际问题中还经常使用一种“先进先出”的数据结构:
即插入在表一端进行,而删除在表的另一端进行,将这种数据结构称为队或队列,把允许插
入的一端叫队尾(rear) ,把允许删除的一端叫队头(front)。
二. 队列的存储实现及运算实现
与线性表、栈类似,队列也有顺序存储和链式存储两种存储方法。
1.顺序队列
循环队列的类型定义如下:
#define MAXQSIZE 100 //最大队列长度
typedef struct {
QElemType *base; //动态分配存储空间
int front; //头指针,若队列不空,指向队列头元素
int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;
下面是循环队列上基本操作的实现。
(1)入队:
int EnQueue (SqQueue &Q, QElemType e) {
if((Q.rear+1)%MAXQSIZE == Q.front) return ERROR;
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1) % MAXQSIZE;
return OK;
}
(2)出队:
int DeQueue (SqQueue &Q, QElemType &e) {
if (Q.front = = Q.rear) return ERROR;
e = Q.base[Q.front];
Q.front = (Q.front+1) % MAXQSIZE;
return OK;
}
(3)求循环队列元素个数:
int QueueLength(SqQueue Q){
return (Q.rear-Q.front+MAXQSIZE) %MAXQSIZE;
}
2.链队列
链式存储的队称为链队列。和链栈类似,用单链表来实现链队列,根据队的先进先出原
则,为了操作上的方便,分别需要一个头指针和尾指针。
链队列的形式描述如下:
typedef struct QNode { // 结点类型
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct { //链队列类型
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
} LinkQueue;
定义一个指向链队列的指针:LinkQueue Q;
下面是链队列的基本运算的实现。
(1)入队
int EnQueue (LinkQueue &Q, QElemType e) {
QNode *p;
p = (QNode *)malloc(sizeof(QNode));
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return OK;
}
(2)出队
int DeQueue (LinkQueue &Q, QElemType &e) {
if (Q.front == Q.rear) return ERROR; //队空,出队失败
p = Q.front->next;
e = p->data; //队头元素放 e 中
Q.front->next = p->next;
if(Q.rear==p) Q.rear= Q.front; //只有一个元素时,此时还要修改队尾指针
free (p);
return OK;
}
3.除了栈和队列之外,还有一种限定性数据结构是双端队列。
(1)双端队列:可以在双端进行插入和删除操作的线性表。
(2)输入受限的双端队列:线性表的两端都可以输出数据元素,但是只能在一端输入数
据元素。
(3)输出受限的双端队列:线性表的两端都可以输入数据元素,但是只能在一端输出数
据元素。