队列
队列的顺序存储
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.输出受限的双端队列:允许一端进行插入和删除操作,在另一边则只可以进行输入操作。