队列:顾名思义是一种排队的形式存储与释放数据,先进先出,先进入队列的排在前边,先输出,后进入队列的排在后边后出队列。队列起始仅仅基于顺序表增加了两个指针,一个指向顺序队列的起始端,一个指向顺序队列的末端,当每次删除一个元素时,头指针后移,每次存入一个数据时,尾指针后移,当头指针与尾指针指向同一个空位置结点时,这是的队列为空队列。
另一个特殊的队列就是循环队列,循环是人为臆造出来的,就是当尾指针达到了最大长度的时候让他再次指向顺序队列的起始地址,当它和头指针指向同一个地址区域时,说明此时的循环队列为空队列。这样相较于一般队列更有效的利用了存储空间。
循环队列关键是设置标志位或者尾指针后头指针前设置一个空的元素空间来表示此时队列已满,本实验就是如此,所以在申请空间大小时要预先多申请一个空间单位。“(Q.rear+1)%LIST_INIT_SIZE==Q.front)”这里的+1就是加上了空空间,避免了Q.rear==Q.front 的情况,因为队列的起始情况就满足Q.rear==Q.front,不能这样设置。这里最好是敲代码验证以下,文字说明不太清晰。
(本实验是针对循环队列写的)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define OK 1
#define TRUE 1
#define ERROR 0
#define FALSE 0
#define LIST_INIT_SIZE 7
typedef int Status;
typedef Status ElemType;
typedef struct{
ElemType *elem;
ElemType front;
ElemType rear;
}SQueue;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
Status InitList(SQueue &Q);
Status Queuelength(SQueue &Q);
Status EnQueue(SQueue &Q,ElemType i);
Status DelQueue(SQueue &Q,ElemType &i);
int main(int argc, char *argv[]) {
ElemType k,j,m,u,c,d;
SQueue Q,L;
InitList(Q);
L=Q;
//检测初始化函数InitList和插入元素函数EnQueue
printf("请输入往队列中填充的数据:");
for(j=0;j<LIST_INIT_SIZE-1;j++){
scanf("%d",&m);
EnQueue(Q,m);
}
for(j=0;j<LIST_INIT_SIZE-1;j++){
printf("%d ",*(L.elem+j));
}
printf("\n");
//检测队头删除元素函数DelQueue以及检测队列长度函数Queuelength
//删除队头的两个元素
printf("删除的队头元素依次是:");
for(j=0;j<2;j++){
DelQueue(Q,c);
printf(" %d ",c);
}
printf("\n");
d=Queuelength(Q);
printf("删除后队列的元素顺序:");
k=Q.front;
for(j=0;j<d;j++){
printf(" %d ",*(Q.elem+((k)%LIST_INIT_SIZE)));
k++;
}
printf("\n");
printf("继续插入元素(验证循环存储):");
for(j=0;j<2;j++){
scanf("%d",&u);
EnQueue(Q,u);
}
printf("\n");
d=Queuelength(Q);
printf("插入元素后的队列顺序:");
for(j=0;j<d;j++){
printf(" %d ",*(Q.elem+((Q.front++)%LIST_INIT_SIZE)));
}
return 0;
}
Status InitList(SQueue &Q){
Q.elem=(ElemType*)malloc(sizeof(ElemType)*LIST_INIT_SIZE);
if(Q.elem==NULL){
printf("动态内存申请失败;");
}else{
Q.front=Q.rear=0;
}
return OK;
}
Status Queuelength(SQueue &Q){ //在L的第i个元素前插入元素e
return (Q.rear-Q.front+LIST_INIT_SIZE)%LIST_INIT_SIZE;
//这里就是一个拟循环的过程
}
Status EnQueue(SQueue &Q,ElemType i){ //在队尾插入元素i
if((Q.rear+1)%LIST_INIT_SIZE==Q.front){ //这里Q.rear+1的原因是在队尾加少用一个空间表示队满状态,因为队满不能用Q.rear=Q.front表示
//所以在申请的队列空间大小与队满的情况差值为1个空间单位。(少用了一个空间单位)
return ERROR;
}
*(Q.elem+Q.rear)=i;
Q.rear=(Q.rear+1)%LIST_INIT_SIZE;
return OK;
}
Status DelQueue(SQueue &Q,ElemType &i){ //用i返回其值
if(Q.front==Q.rear){
return ERROR;
}else{
i=*(Q.elem+Q.front);
Q.front=(Q.front+1)%LIST_INIT_SIZE;
return OK;
}
}
运行结果: