参考书籍:数据结构(C语言版)严蔚敏吴伟民编著清华大学出版社
本文中的代码可从这里下载:https://github.com/qingyujean/data-structure
顺序队列的类型定义如下:
#define maxsize 100/*队列的最大容量*/
typedef char QElemtype;
struct Queue
{ QElemtype data[maxsize ]; //队员的存储空间
int front; //队头队尾指针
int rear; //队尾指针
};
定义一个顺序队的变量: Queue Q;
队列的数据区为:Q.data[0]---Q.data[maxsize -1]
队头指针:Q.front 队尾指针:Q.rear
约定队头指针指向队头元素,队尾指针指向队尾元素后面一个位置(这样的设置是为了某些运算的方便,并不是唯一的方法)。
从下图中可以看到,随着入队出队的进行,会使整个队列整体向后移动,这样就出现了图(d)中的现象:队尾指针已经移到了最后,再有元素入队就会出现溢出,而事实上此时队中并未真的“满员”,这种现象为“假溢出”,这是由于“队尾入队头出”这种受限制的操作所造成。
解决上面的问题一个巧妙的方法就是:将顺序队列臆造成一个环状的空间,如下图,称之为循环队列。
顺序循环队列的定义
#define MAXSIZE 30
typedef char QElemType;
typedef struct{
QElemType data[MAXSIZE];
int f;//头指针
int r;//尾指针
}SqQueue;
因为是头尾相接的循环结构,入队时的队尾指针加1操作修改为:Q.rear=(Q.rear+1) % (n0+1);
出队时的队头指针加1操作修改为:Q.front=(Q.front+1) % (n0+1);
设n0=9,图是循环队列操作示意图。
从图的循环队可以看出,在队空情况下有:front==rear,在队满情况下也有:front==rear就是说“队满”和“队空”的条件是相同的了。这显然是必须要解决的一个问题。
方法之一是附设一个存储队中元素个数的变量如num,当num==0时队空,当num==maxsize时为队满。
另一种方法是少用一个元素空间,把图(d)所示的情况就视为队满,此时的状态是队尾指针加1就会从后面赶上队头指针,这种情况下队满的条件是:(rear+1) % maxsize ==front,也能和空队区别开。
下面的循环队列及操作按第二种方法实现。
队空:front==rear
队满: (rear+1) mod maxsize ==front
队中元素个数n=(rear-front+maxsize )mod maxsize
入队:rear=(rear+1) % maxsize ;
出队:front=(front+1) % maxsize ;
/*顺序循环队列:少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置(环状的下一位置)上”作为队列“满”状态的标志
即,队满:Q.f == (R.r + 1)%MAXSIZE
对空:Q.f == Q.r
队长:(Q.r - Q.f + MAXSIZE)%MAXSIZE
入队时尾指针后移:Q.r = (Q.r + 1)%MAXSIZE
出队时头指针后移:Q.f = (Q.f + 1)%MAXSIZE
*/
#include
#define MAXSIZE 30
typedef char QElemType;
typedef struct{
QElemType data[MAXSIZE];
int f;//头指针
int r;//尾指针
}SqQueue;
//初始化一个空队列
void initQueue(SqQueue &Q){
Q.f = Q.r = 0;
}
//求队列长度
int getQueueLength(SqQueue Q){
return (Q.r - Q.f + MAXSIZE)%MAXSIZE;
}
//入队操作,尾指针后移
void enQueue(SqQueue &Q, QElemType e){
//先判断队列是否已满
if(Q.f == (Q.r + 1)%MAXSIZE){
printf("队列已满,入队操作失败!\n");
return;
}
Q.data[Q.r] = e;
Q.r = (Q.r + 1)%MAXSIZE;
}
//出队操作,头指针后移,e返回出队元素值
void deQueue(SqQueue &Q, QElemType &e){
//先判断队列是否为空
if(Q.f == Q.r){
printf("队列已空,出队操作失败!\n");
return;
}
e = Q.data[Q.f];
printf("元素%c出队\n", e);
Q.f = (Q.f + 1)%MAXSIZE;
}
//利用入队操作创建一个队列,他含有n个元素
void createQueue(SqQueue &Q, int n){
int i = 0;
printf("请输入%d个字符队列元素:\n", n);
while(i < n){
QElemType e;
scanf("%c", &e);
enQueue(Q, e);
i++;
getchar();//吃掉回车符
}
}
void printQueue(SqQueue Q){
printf("打印队列:");
int i = Q.f;
while(i%MAXSIZE != Q.r){
printf("%c ", Q.data[i]);
i++;
}
printf("\n\n");
}
void main(){
SqQueue Q;
initQueue(Q);
createQueue(Q, 5);
printQueue(Q);
printf("执行入队操作:");
printf("请输入您要入队的字符元素:");
QElemType e;
scanf("%c", &e);
enQueue(Q, e);
printQueue(Q);
printf("执行出队操作:");
deQueue(Q, e);
printQueue(Q);
}