队列是一种特殊的线性表,特殊之处在与允许在表的前端(front)进行删除操作,而在表ide后端进行插入操作,和栈一样,队列时一种操作受限制的线性表,进行
插入操作的端称为队尾,进行删除操作的端称为队头。
队列的数据元素称为队列元素,在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队,因为队列只允许在一段插入,一端删除,所以只有最早进入队列
的元素才能从队列中删除,故队列由称为先进先出(fifo)
顺序队列
建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理,一个是队头指针front,它指向队头元素,一个是队尾指针rear,它指向下一个入队元素,位置,每次在队尾插入一个元素,rear增加1;每次在队头删除一个元素,front增加1,随着插入和删除的操作进行,队列元素的各数不断变化,队列占的存储空间在队列结构分配的连续空间中移动,当Front=rear时,队列中每有任何元素,称为空队列,当rear增加到指向分配的连续空间之外,队列无法在插入新元素,但这时往往还有大量的可用的空间未被占用,这些空间是已经出对的队列元素占用过的存储单元。
队尾指针指向队尾元素的下一个位置(也可以让rear指向队尾元素,front指向队头元素的前一个位置,)
循环队列
在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进,无论插入或删除,一旦rear指针增加1或front指针增加1时超出分配的队列空间,就让它执行这片连续空间的起始位置,自己真从MaxSize-1曾1变到0,可用取运算rear% Maxsize和Front%MaxSize来实现,这实际上是吧队列空间想象成一个环形空间,环形空间中存储短语循环使用,用这种方法管理的队列称为循环队列,
在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满,也有front=rear,为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩一个存储单元时,队列就已经满了,因此,队列判空时front=rear,而队列判满时front=(rear+1)%MaxSize.
typedef struct QNode{
ElemType data;
struct QNode *next;
}QNode;
typedef struct LinkQueue{
QNode *front; //指向队头元素
QNode *rear; //指向队尾元素
}LinkQueue;
Status InitQueue(LinkQueue *q)
{
q->front=q->rear=(QNode*)malloc(sizeof(QNode)); //分配内存空间
if(!q->front)
return error;
q->front->next=null;
return OK;
}
Status EnQueue(LinkQueue *q,ElemType e) //插入队列
{
QNode *p=(QNode*)malloc(sizeof(QNode));
if(!p)
return error;
p->data=e;
p->next=null;
p->rear->next=p; //将新地址保存,入队操作,从队尾(rear)进入
q->rear=p; //相当于rear++,q->rear指向下一个位置 符合入队操作的基本要求
return OK;
}
Status DeQueue(LinkQueue *q,ElemType *e)
{
QNode *p=(QNode *)malloc(sizeof(QNode));
if(!p)
return error;
p=q->front->next;//q 指向的是Front指针的下一个位置,即队首元素。
*e=p->data;
q->front->next=p->next;//出队操作后,Front++
if(q->rear==p)//判断是否全部出队
q->rear=q->front;//如果全部出队,则将队列置为空
return ok;
}
在循环队列中,Q->front==Q->rear并不能确定队列为空,也有可能是队列已满,所以采用队列头指针在队尾指针的下一位置来判断队列已满(此方法会浪费一个内存空间)。
#define MAXQSIZE 100
typedef struct
{
QElemType *base;
int front;
int rear;
int queuesize;
}SqQueue;
Status InitQueue(SqQueue *Q)
{
Q->queuesize=MAXQSIZE;
Q->base=(QElemType*)malloc(Q->queuesize *sizeof(QElemType));
if(Q->base==NULL)
{
return ERROR;
}
Q->front=Q->rear=0;
return OK;
}
int QueueLength(SqQueue *Q)
{
return((Q->rear-Q->front+Q->queuesize)%Q->queuesize);
}
Status EnQueue(SqQueue *Q,QEletype e)
{
//在循环队列中,Q->front==Q->rear并不能确定,队列为空,也有可能是队列已满
//所以采用队列头指针在队尾指针的下一位置来判断队列已满
if((Q->rear+1)%Q->queuesize==Q->front)
{
Q->base =(QElemType*)realloc(Q->base,Q->queuesize);
if(Q->base==null)
return error;
Q->queuesize*=2;
}
Q->bse[Q->rear]=e;
Q->rear=(Q->rear+1)%Q->queuesize;
return OK;
}
Status DeQueue(SqQueue *Q,QElemType *e)
{
if(Q->front==Q->rear)
{
return error;
}
*e=Q->base[Q->front];
Q->front=(Q->front+1)%Q->queuesize;
return OK;
}
Status DestroyQueue(SqQueue*Q)
{
free(Q->base);
return OK;
}
int main()
{
SqQueue Q;
QElemType e;
int i;
InitQueue(&Q)
for(i=0;i<MAXQSIZE*10;++i)
{
if(EnQueue(&Q,i)!=OK)
return -1;
while(Q.front!=Q.rear)
{
DeQueue(&Q,&e);
printf("%d\n",e);
}
DestroyQueue(&Q);
return 0;
}
}