基本概念
队列是只允许在一端进行插入, 在另一端删除的线性表
队列的特点: 先进先出
队列的常见操作
InitQueue(&Q)
: 初始化队列, 构造一个空队列Q
DestoryQueue(&Q)
: 销毁队列, 销毁并释放队列Q所占用的内存空间
EnQueue(&Q,x)
: 入队, 若队列Q未满, 将x加入, 使之成为新的队尾
DeQueue(&Q,&x)
: 出队, 若队列Q非空, 删除队头元素, 并用x返回
GetHead(Q, &x)
: 读对头元素, 若队列Q非空, 则将队头赋值给x
QueueEmpty(Q)
判断队列空 , 若队列Q为空返回true, 否则返回false
队列的存储顺序
假设队列的元素个数最大不超过整数MAXSIZE, 所有的元素都具有同一数据类型QElemType, 则顺序队列类型SqQueue定义如下:
#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //用静态数组存放队列元素
int front , rear; //队头指针和队尾指针
}SqQueue;
初始化队列
void InitQueue(SqQueue &Q){
//初始化时队头和队尾指针指向0
Q.rear = Q.front = 0;
}
判断队列是否为空
bool QueueEmpty(SqQueue Q){
if(Q.rear==Q.front){
return true;
}else{
return false;
}
}
循环队列
有front==rear成立, 该条件可以作为队空的条件
能否用rear==MAXSIZE作为队满的条件呢?
不能, 在图(a)中, 队列不满, 但却满足该条件
这是入队会出现"上溢出", 队列仍存在可存放元素的空位置, 所以这种情况是假溢出
为充分使用顺序队列中的存储空间, 把顺序队列的首尾相连接, 形成一个环, 即循环队列
入队EnQueue(&Q, x)
入队, 若队列Q未满, 将x加入, 使之成为新的队尾
#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //用静态数组存放队列元素
int front , rear; //队头指针和队尾指针
}SqQueue;
入队
bool EnQueue(SqQueue Q, ElemType x){
if(队列已满){
return false;
}
Q.data[Q.rear]=x;//将x插入队尾
Q.rear=Q.rear+1;//队尾指针后移
return true;
}
循环队列的入队
bool EnQueue(SqQueue Q, ElemType x){
if(Q.front == Q.rear){//队列已满
return false;
}
Q.data[Q.rear]=x;//将x插入队尾
Q.rear=(Q.rear+1)%MaxSize;//队尾指针后移
return true;
}
循环队列基本操作的实现
初始化空队
Q.front = Q.rear = 0;
入队
Q.rear=(Q.rear+1)%MaxSize;
出队
Q.front=(Q.front+1)%MaxSize;
队空条件
Q.front == Q.rear;
//由于出队的Q.front追上了Q.rear
队满条件
Q.front == Q.rear;
//由入出队的Q.rear追上了Q.front
如何区分循环队列的对空、队满
在入队时少用一个数据元素空间, 以队尾指针加1等于队头指针判断队满
即队满条件为:
(Q.rear+1)%MaxSize==Q.front
队空条件仍为
Q.rear == Q.front
队列元素个数
( rear + MaxSize - front ) % MaxSize
循环队列初始化队列
Status InitQueue(SqQueue &Q){
Q.base = (QElemType *) malloc (MaxSize * sizeof(QElemType ));
if(!Q.base){
exit(OVERFLOW);
}
Q.front = Q.rear = 0;
return OK;
}
求队列的长度
int QueueLength(SqQueue Q){
return (Q.rear - Q.front + MaxSize)%MaxSize;
}
入队列
判断队列是否为空
bool QueueEmpty(SqQueue Q){
if(Q.rear==Q.front){
return true;
}else{
return false;
}
}
入队
bool EnQueue(SqQueue &Q, ElemType x){
if((Q.rear+1)%MaxSize==Q.front){
return false;//队满则报错
}
Q.data[Q.rear]=x;//新元素插入队尾
Q.rear=(Q.rear+1)%MaxSize;//队尾指针加1取模
return true;
}
出队列
int DeQueue(SqQueue &Q, QEmleType &e){
if(Q.front==Q.rear){
return ERROR;//对空
}
e=Q.base[Q.front];
Q.front=(Q.front+1)%MaxSize;//队头位置发生变化
return OK;
}
队列的链式存储
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct {//链式队列
LinkNode *front , *rear;//队列的对头和队尾指针
}LinkQueue;
初始化队列InitQueue(&Q)
(带头结点)
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct {//链式队列
LinkNode *front , *rear;//队列的对头和队尾指针
}LinkQueue;
初始化队列
void InitQueue(LinkQueue &Q){
//初始化时,front,rear都指向头结点
Q.front=Q.rear=(LinkQueue*)malloc(sizeof(LinkNode));//申请结点空间
Q.front->next=NULL;
}
判断对列是否为空
bool IsEmpty (LinkQueue Q){
if(Q.front==Q.rear){
return true;
}else{
return false;
}
}
初始化队列InitQueue(&Q)
(不带头结点)
初始化队列(不带头结点)
void InitQueue(LinkQueue &Q){
//初始化时,front,rear都指向NULL
Q.front=NULL;
Q.rear=NULL;
}
判断对列是否为空
bool IsEmpty (LinkQueue Q){
if(Q.front==NULL){
return true;
}else{
return false;
}
}
入队列EnQueue(&Q , e)
(带头结点)
新元素入队(带头结点)
void EnQueue(LinkQueue &Q, ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
Q.rear->next=s;//新结点插入到rear之后
Q.rear=s;//修改表尾指针
}
入队列EnQueue(&Q , e)
(不带头结点)
void EnQueue(LinkQueue &Q, ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
if(Q.front==NULL){
Q.front = s;
Q.rear = s;
}else{
Q.rear->next=s;//新结点插入到rear之后
Q.rear=s;//修改表尾指针
}
}
出队列EnQueue(&Q , e)
(带头结点)
bool DeQueue(LinkQueue Q, ElemType &x){
if(Q.front==Q.rear){
return false;//空队
}
LinkNode *p = Q.front->next;
x=p->data;//用变量x返回队头元素
Q.front->next = p->next;//修改头结点的next指针
if(Q.rear==p){//此次是最后一个结点出队
Q.rear=Q.front;//修改rear指针
}
free(p);//释放结点空间
return true;
}
当删成最后一个结点
出队列EnQueue(&Q , e)
(不带头结点)
bool DeQueue(LinkQueue Q, ElemType &x){
if(Q.front==Q.rear){
return false;//空队
}
LinkNode *p = Q.front;
x=p->data;//用变量x返回队头元素
Q.front = p->next;//修改头结点的next指针
if(Q.rear==p){//此次是最后一个结点出队
Q.rear=NULL;
Q.front=NULL;
}
free(p);//释放结点空间
return true;
}
双端队列
只允许从两端插入, 两端删除的线性表
输入受限的双端队列: 只允许从一端插入, 两端删除的线性表
输出受限的双端队列: 只允许从两端插入, 一端删除的线性表