队列的顺序存储
1.队列的定义:队列是一种操作受到限制的线性表,它只允许在队列的一段进行插入操作,而在另一端进行删除操作。(就如同在排队一般,先排队的人员先进行办理业务)---即先进先出。
队列示意图:
2.队列的数据结构定义:
define Maxsize 50
typedef struct{
Elemtype data[Maxsize]; //存放队列元素
int front,rear; //队头指针与队尾指针
}SqQueue;
注:当Q.front==Q.rear==0时,表示该队列为空队。
当入队时,队尾指针rear=rear+1;当出队时,队头指针front=front+1。
问题:当不断地入队与出队后,会产生一个问题:当Q.front==Q.rear==Maxsize时,即便只有一个元素时,也无法再进行入队操作。---即“假溢出”
针对这个问题请看循环队列。
循环队列
定义:虽然称之为循环队列,但实际上所谓的循环只是逻辑上的循环,实际上在存储空间中依旧是顺序队列,与顺序队列所不同的是实际上是循环队列的入队操作与出队操作时,队头指针与队列指针的移动规则不同。
入队时:Q.rear=(Q.rear+1)%Maxsize;
出队时:Q.front=(Q.front+1)%Maxsize;
判断队满时条件:(Q.rear+1)%Maxsize==Q.front;
判断队空时条件:Q.front==Q.rear;
循环队列基本操作:初始化;判队空;入队;出队
初始化:
void initQueue(sqQueue Q){
Q.front=Q.rear=0;
return Q;
}
判队空:
void IsEmpty(sqQueue Q){
if(Q.front==Q.rear)
return true;
else
return false;
}
入队:
void EnQueue(sqQueue Q,Elemtype x){
if((Q.rear+1)%Maxsize==Q.front) //队列已满,无法再入队
return false;
else{
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%Maxsize;
}
}
出队:
Void GetQueue(sqQueue Q,Elemtype x){
if(Q.front==Q.rear)
return false;
else{
x=Q.data[Q.front];
Q.front=(Q.front+1)%Maxsize;
}
}
队列的链式存储
1.定义:实际上它是带有头指针和尾指针的单链表,头指针指向的是队头结点,尾指针的指向的是队尾结点。
2.数据结构定义
typedef struct{ //链式队列结点结构定义
Elemtype data;
Struct LinkNode *next;
}LinkNode;
Typedef struct{ //链式队列
LinkNode *front,*rear; //头指针与尾指针定义
}LinkQueue;
3.链式队列的基本操作:初始化;判队空;入队;出队
初始化:
void initQueue(LinkQueue &Q){
Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
判队空:
Void IsEmpty(LinkQueue Q){
if(Q.front==Q.rear)
return true;
else
return false;
}
入队:
void EnQueue(LinkQueue &Q,Elemtype x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
Q.rear->next=s;
Q.rear=s;
}
出队:
Void GetQueue(LinkQueue &Q,Elemtype &x){
if(Q.queue==Q.rear) return false; //空队时报错
LinkNode *p=Q.front;
x=p->data;
Q.front=p->next;
if(Q.rear==p)
Q.rear=Q.rear;
free(p);
}
双端队列
定义:可以在队列两边都进行插入与删除操作的队列。
衍生:
1.输入受限的双端队列:允许一端进行插入和删除操作,在另一边则只可以进行输出操作。
2.输出受限的双端队列:允许一端进行插入和删除操作,在另一边则只可以进行输入操作。
练习题:
42. ( 10 分 ) 请设计一个队列,要求满足: ① 初始时队列为空; ② 入队时,允许增加队列占用空间; ③ 出队后,出队元素所占用的空间可重复使用,即整个队列所占用的空间只增不减; ④ 人队操作和出队操作的时间复杂度始终保持为 O(1) 。请回答下列问题:
( 1 ) 该队列应该选择链式存储结构,还是顺序存储结构?
( 2 ) 画出队列的初始状态,并给出判断队空和队满的条件
( 3 ) 画出第一个元素 入 队后的队列状态。
( 4 ) 给出入队操作和出队操作的基本过程。
1.应该使用链式存储结构。根据条件2的要求需要灵活的增加队列的占用空间。
2.根据条件3元素占用的空间需要可重复使用,所以推断需要的是循环队列。
初始化创建之后,只有一个空白结点及指向其的头指针front和尾指针rear。
队空条件:rear==front
队满条件:rear->next==front