#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int ElemType;
#define MaxSize 10
//队列的定义
typedef struct SqQueue
{
ElemType data[MaxSize];
int front, rear;//front为头指针,rear为尾指针。这里并不是真正的“指针”
}SqQueue;
SqQueue q;
void InitQueue(SqQueue* q);//初始化队列
bool EnQueue(SqQueue* q, ElemType x);//入队操作
bool PopQueue(SqQueue* q);//出队操作
bool Gethead(SqQueue* q);//取队头元素
void PrintQueue(SqQueue* q);//打印队列元素
void InitQueue(SqQueue* q)//初始化队列
{
q->front = q->rear=0;
printf("队列初始化成功\n");
}
bool EnQueue(SqQueue* q,ElemType x)//入队操作
{
if ((q->rear + 1) % MaxSize == q->front)
printf("队列已满,无法完成入队操作\n");
else
{
q->data[q->rear] = x;
q->rear = ((q->rear) + 1) % MaxSize;//因为是循环队列,所以采用这种方式使队尾指针后移
printf("入队成功\n");
}
}
bool PopQueue(SqQueue* q) //出队操作
{
if (q->rear == q->front)
{
printf("该队列为空,无法完成出队操作\n");
}
else
{
int x;
x = q->data[q->front];
q->front = ((q->front) + 1) % MaxSize;//使队头指针后移
printf("出队成功\n");
}
}
bool Gethead(SqQueue* q)//取队头元素
{
if (q->rear == q->front)
{
printf("该队列为空,无法完成出队操作\n");
}
else
{
int x;
x = q->data[q->front];
printf("队头元素为%d",x);
}
}
void PrintQueue(SqQueue q)//打印队列元素
{
while (q.front != q.rear)
{
printf("%d ", q.data[q.front]);
q.front = (q.front + 1) % MaxSize;
}
}
所述代码都是基于队尾指针指向队尾元素后一个位置实现的
队列:
1.只能从一段进行插入,另一端进行删除
2.注意循环队列q->rear=((q->rear)+1)%MaxSize是使指针后移的操作
判断队列已满/为空的操作
方法一:这种判空方式就是上面代码所用的,缺点是会牺牲一个存储单元(因为我们是用rear指针的下一个位置是front来判断队列是否已满)
方法二:定义一个变量来记录队列的长度,入队成功size++,出队size--,
此时队满的判断:size==MaxSize;
方法三:定义一个tag变量来记录最近一次执行的是插入还是删除操作
tag=1表示是插入操作
tag=0表示是删除操作
若rear==front && tag==1 则队列已满
若rear==front && tag==0 则队列为空
补充:
求队列元素的个数
int length(SqQueue L)
{
return ((rear+MaxSize-front)%MaxSize);
}