队列的定义
队列(Queue)是仅在表尾进行插入操作,在表头进行删除操作的线性表。
是一种先进先出(FIFO)的线性表。
顺序队列可由一维数组来实现。
队列所剩余的空间问题(循环队列)
一般情况下,我们会认为当队尾等于MAXSIZE-1时,队列的空间已满。但是,由于我们会不断的进行出队操作,每进行出队操作时队头会向高位移动,此时低位的空间并没有被占用,队尾等于MAXSIZE-1时为假溢出。为了充分利用空间,我们可以将队列视为循环队列,每进行入队出队操作时,队头和队尾移动位置后对MAXSIZE进行模运算即可。
如队列最大长度MAXSIZE为5,队头front为3, 队尾rear为4,此时0,1,2,4位置并未被占用,我们若要将一个元素入队,则将元素放到位置4,然后进行 rear = (rear+1)%MXAXSZIE 操作,此时rear = 0,则下次进行入队操作时候即可从0位置进入。
判断队列为空和队列已满时的矛盾问题
由于我们将队列视为循环队列,则当队列为空时,队头front = 队尾rear;当队列已满时,仍是队头front = 队尾rear。为了解决此矛盾,我们可以弃用一个空间,如队列最大长度MAXSIZE为6,而我们只用5个空间,此时,队空时,队头front = 队尾rear;队满时,则队头front = 队尾rear+1。这样即可有效解决此矛盾。
结构体定义队列及队列元素的数据类型
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 66 //队列最大长度
typedef struct
{
int data;
}Elemtype;
typedef struct
{
Elemtype *elem;
int front; //队头
int rear; //队尾
}Queue;
基本操作函数
void initQueue(Queue* Q);//初始化,构造空队列
void destroyQueue(Queue* Q);//销毁队列
void clearQueue(Queue* Q);//清空队列
int Queuelength(Queue* Q);//队长
int isempty(Queue* Q);//判断队列是否为空
void enQueue(Queue* Q, Elemtype x);//入队
void deQueue(Queue* Q, Elemtype &x);//出队
初始化
为队列元素分配内存空间,将队头和队尾设置为0,即可完成初始化,形成一个空队列。
void initQueue(Queue* Q)//初始化
{
Q->elem = (Elemtype*)malloc(sizeof(Elemtype)*MAXSIZE);
if(Q->elem == NULL)
{
printf("初始化失败!!!\n");
}
Q->front = Q->rear = 0;
printf("初始化成功!!!\n");
return;
}
销毁队列
将所为队列元素分配的空间释放,即可销毁队列。
void destroyQueue(Queue* Q)//销毁队列
{
Q->front = Q->rear = 0;
free(Q->elem);
printf("已销毁!!!\n");
return;
}
清空队列
将队头和队尾设置为0,即可视为空队列。
void clearQueue(Queue* Q)//清空队列
{
Q->front = Q->rear = 0;
}
队长
由于可能存在队头位于高位,队尾位于低位的情况,若直接将队尾与队头的差值对MAXSIZE进行模运算,所得的长度有误。为了避免这种错误,我们只需将队尾与队头的差值加上MAXSIZE,再对MAXSIZE进行模运算即可。
int Queuelength(Queue* Q)//求队长
{
return (Q->rear - Q->front + MAXSIZE)%MAXSIZE;
}
判断队列是否为空
上面有详细分析
int isempty(Queue* Q)//判断队列是否为空
{
if(Q->rear == Q->front)
return 1;
else
return 0;
}
入队
入队前,需要先判断队列是否已满,若队列已满,则无法入队,若未满,则将入队元素放置队尾位置,再将队尾往后移动一个位置,即可完成入对操作。
void enQueue(Queue* Q, Elemtype x)//入队
{
if((Q->rear+1)%MAXSIZE == Q->front)
{
printf("队列已满!!!\n");
return;
}
Q->elem[Q->rear] = x;
Q->rear = (Q->rear+1)%MAXSIZE;
printf("入队成功!!!\n");
return;
}
出队
出队前,需要判断队列是否为空,若队列为空,则无法进行出队操作,若不为空,则接受队头位置元素,再将队头往后移动一个位置,即可完成出队操作。
void deQueue(Queue* Q, Elemtype &x)//出队
{
if(Q->rear == Q->front)
{
printf("队列为空!!!\n");
return;
}
x = Q->elem[Q->front];
Q->front = (Q->front+1)%MAXSIZE;
printf("出队成功!!!\n");
return;
}
main函数
自行调用函数进行操作即可。
int main(void)
{
Queue* Q = (Queue*)malloc(sizeof(Queue));
Elemtype x, y;
x.data = 666;
initQueue(Q);
enQueue(Q, x);
deQueue(Q, y);
printf("%d\n", y.data);
//clearQueue(Q);
//destroyQueue(Q);
if(isempty(Q))
printf("队列为空!!\n");
else
printf("队列不为空!!\n");
int len = Queuelength(Q);
printf("len = %d\n", len);
return 0;
}