目录
一. 前言
队列是仅在表尾进行插入操作,在表头进行删除操作的特殊线性表。它是一种先进先出的线性表。队列的存储结构有两种,分别为链队和顺序队(一般是循环顺序队,也叫循环队)。
二. 循环队列
我们循环队列就是为了解决队列假上溢而设计的方法。
队列的结构定义如下:
#define MAXQSIZE 100
typedef struct{
QElemType * base; //初始化的动态分配存储空间
int front; //第一个位置
int rear; //最后一个位置
}SqQueue;
在定义好队列的结构之后,我们来进行下循环队列的初始化
int InitQueue(SqQueue &Q){
Q.base=new QELemType[MAXQSIZE];
if(!Q.base) return -1;
Q.front=Q.rear=0; //都置为0,表示队列为空
return 1;
}
求 循环队列的长度:
int QueueLength(SqQueue Q){
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE);
}
这里由于可能会出现假溢出的情况,会出现Q.front>Q.rear的情况,因此需要给Q.rear再加上一个MAXQSIZE,再对它们取余就能得到队列当中的元素个数,也就是循环队列的长度。
循环队列的入队:
int EnQueue(SqQueue &Q,QElemType e){
if((Q.rear+1)%MAXQSIZE==Q.front) return -1; //这是判断循环队列是否队满的条件
Q.base[Q.rear]=e; //新元素加入队尾
Q.rear=(Q.rear+1)%MAXSIZE; //队尾指针加一
return 1;
}
循环队列的出队:
int OutQueue(SqQueue &Q,QElemType &e){
if(Q.front==Q.rear) return -1; //判断循环队列是否为空的条件
e=Q.base[Q.front]; //取出队头元素
Q.front=(Q.front+1)%MAXQSIZE; //队头指针加一
return 1;
}
三. 链队列
若是我们用户无法估计所用队列的长度,则应该采用链队列。
链队列的结构类型定义如下:
#define MAXQSIZE 100; //最大队列长度
typedef struct Qnode{
QElemType data;
struct Qnode * next;
}Qnode,*Queue;
typedef struct{
Queue front; //队头指针
Queue rear; //队尾指针
}LinkQueue;
跟循环队列的定义不一样,我们这里的front和rear都是指针,指向Queue这个结构类型。而我们上面循环队列的则只是队头和队尾的一个记录序号。
链队列的初始化如下:
int InitQueue(LinkQueue &Q){
Q.front=Q.rear=new Qnode;
if(!Q.front) return -1;
Q.front->next=NULL;
return 1;
}
链队列的销毁:
int DestroyQueue(LinkQueue &Q){
while(Q.front){
p=Q.front->next;
free(Q.front);
Q.front=p;
}
}
链队列的入队:
int EnQueue(LinkQueue &Q,QElemType e){
Qnode* p=new Qnode;
if(!p) return -1;
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return 1;
}
链队列的出队:
int OutQueue(LinkQueue &Q,QElemType &e){
if(Q.front==Q.rear) return -1;
Qnode* p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front; //特殊情况,当队中只有一个元素的时候,还需要修改尾指针rear
delete p;
return 1;
}
取链队列的队头元素:
int GetHead(LinkQueue Q,QElemType &e){
if(Q.front==Q.rear) return -1;
e=Q.front->next->data;
return 1;
}
以上便是我们循环队列和链队列的所有内容。