队列是一种先进先出的顺序表,在一端(队尾rear)插入,另一端(队头front)删除。
为了节省空间,顺序队列采用循环的方式存储数据(可以把它想象成一个环)。
队列为空时rear和front指向同一下标,队列满时也会指向同一位置。为了区分这两种情况,有两种处理方法:
1.人为的将队列空出一格不存数据,空队列rear==front,满队列(rear+1)%QueueSize==front
2.设置一个flag标志队列为空或满
本文采用方法一
定义循环队列
类似这样
typedef int QElemType;
#define MAXSIZE 10
typedef struct//不支持扩容
{
QElemType* base;//指向“数组”
int front;//队头,第一个数据的下标
int rear;//队尾,当前可以存放数据的下标
}SqQueue, * PSqQueue;
初始化
void InitQueue(PSqQueue pq)
{
assert(pq != NULL);
pq->base = (QElemType*)malloc(MAXSIZE * sizeof(QElemType));
assert(pq->base != NULL);
if (pq->base == NULL)
{
perror("InitQueue");
return;
}
//初始头尾下标都为0
pq->front = 0;
pq->rear = 0;
}
获得有效数据个数
int GetLength(PSqQueue pq)
{
assert(pq != NULL);
if (pq == NULL)
return -1;
int len = (pq->rear - pq->front + MAXSIZE) % MAXSIZE;
return len;
}
判空
front和rear指向同一位置
bool IsEmpty(PSqQueue pq)
{
return pq->front == pq->rear;
}
判满
队尾再往后走一步就是头
static bool IsFull(PSqQueue pq)
{
return (pq->rear + 1) % MAXSIZE == pq->front;
}
入队
bool Push(PSqQueue pq, QElemType val)
{
if (IsFull(pq))//判断是否可以入
return false;
pq->base[pq->rear] = val;//rear指向的是能放数据的地方
pq->rear = (pq->rear + 1) % MAXSIZE;//更新rear
return true;
}
出队
bool类型判断是否出队成功,必须传参把队头值带出去
bool Pop(PSqQueue pq, QElemType* rtval)
{
if (IsEmpty(pq))//判断能否出队
return false;
*rtval = pq->base[pq->front];
pq->front = (pq->front + 1) % MAXSIZE;
return true;
}
获取对头值,不删除
bool GetHead(PSqQueue pq, QElemType* rtval)
{
if (IsEmpty(pq))
return false;
*rtval = pq->base[pq->front];
return true;
}
清空数据
头和尾指向一处就为空
void Clear(PSqQueue pq)
{
pq->front = pq->rear = 0;
}
销毁内存
free掉初始化时malloc的base空间,并且指向NULL(防止多次销毁)
void Destroy(PSqQueue pq)
{
free(pq->base);
pq->base = NULL;
pq->front = pq->rear = 0;
}