队列与栈类似,也同样基于线性表.
他的特点是:先进先出.
如我们日常说的队列一样,后来的人后走,先来的人先走.下面用图片形象的展示一下:
队列有队头和队尾,队头是先进入的元素,队尾是后进入的元素
他同样有两种存储模式,分别实现一下:
链式:
/*************************************************************************
> File Name: 队列的实现.c
> Author: zhanghaoran
> Mail: chilumanxi@gmail.com
> Created Time: 2015年07月22日 星期三 20时35分35秒
************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define OVERFLOW -2
#define OK 1
#define ERROR 0
//链表
//队列元素的数据
typedef struct cQueue{
int data;
struct cQueue *next;
}QNode, *QueuePtr;
typedef struct{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
int InitQueue(LinkQueue &Q){
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));
if(Q.front == NULL)
exit(OVERFLOW);
Q.front -> next = NULL;
return OK;
}
int DestroyQueue(LinkQueue &Q){
while(Q.front != NULL){
Q.rear = Q.front -> next;
free(Q.front);
Q.front = Q.rear;
}
return OK;
}
int EnQueue(LinkQueue &Q, int e){
QueuePtr q;
q = (QueuePtr)malloc(sizeof(QNode));
q -> data = e;
q -> next = NULL;
Q.rear -> next = q;
Q.rear = q;
return OK;
}
int DeQueue(LinkQueue &Q){
QueuePtr q;
int e;
if(Q.front == Q.rear)
return ERROR;
q = Q.front -> next;
e = q -> data;
Q.front -> next = q -> next;
if(Q.rear == q)
Q.rear = Q.front;
free(q);
return e;
}
int ClearQueue(LinkQueue &Q){
QueuePtr q;
q = Q.front;
while(q -> next != NULL){
Q.front = Q.front -> next;
free(q);
q = Q.front;
}
Q.rear = NULL;
return OK;
}
int QueueEmpty(LinkQueue Q){
if(Q.front -> next == NULL)
return OK;
else
return ERROR;
}
int GetHead(LinkQueue Q){
if(!QueueEmpty(Q))
return Q.front -> next -> data;
else
return ERROR;
}
int main(void){
LinkQueue Queue;
int a[8] = {3, 8, 5, 17, 9, 30, 15, 22};
int i;
InitQueue(Queue);
for(i = 0; i < 8; i ++){
EnQueue(Queue, a[i]);
}
printf("%d ", DeQueue(Queue));
printf("%d ", DeQueue(Queue));
EnQueue(Queue, 68);
printf("%d ", GetHead(Queue));
printf("%d ", GetHead(Queue));
while(!QueueEmpty(Queue)){
printf("%d ", DeQueue(Queue));
}
printf(" ");
ClearQueue(Queue);
return 0;
}
当然需要注意一点就是出队的时候如果恰好出队的是队尾元素的话,那就要让队尾元素指向头结点,否则队尾指针将会丢失.
好的,下面我们给出一个经常使用的数据结构的数组实现:
#include <stdio.h>
#include <stdlib.h>
#define OVERFLOW -2
#define OK 1
#define ERROR 0
#define INIT_QUEUE_SIZE 100
int Queue[INIT_QUEUE_SIZE];
int flag = 0;
int front = 0, rear = 0;
int len = 0;
void CreatQueue(){
if(flag == 1)
printf("队列已经存在。");
else {
for(int i = 0; i < 6; i ++){
printf("输入初始化的第%d个数", i);
scanf("%d", &(Queue[i]));
len ++;
}
rear = 5;
flag = 1;
}
}
void EnQueue(){
if( !flag ) printf("当前无队列,请创建队列!\n");
else {
printf("请输入入队列的元素:");
scanf("%d", &Queue[rear + 1]);
rear ++;
len ++;
}
}
void DeQueue(){
if( !flag ) printf("当前无队列,请创建队列!\n");
else {
printf("出队列的元素%d", Queue[front]);
front ++;
len --;
printf("出队列后的队列为:\n");
for(int i = front; i <= rear; i ++)
printf("%d", Queue[i]);
}
}
void print(){
printf("\n当前队列为:");
for(int i = front; i < len; i ++)
printf("%d ",Queue[i]);
}
在数组的情况下,我们只需要定义两个整型作为队尾和队头就可以了,非常的简便,在ACM以及各种算法题目中,这种形式是最长用的,比如BFS.详情使用见我的博客的另外两篇文章:http://blog.csdn.net/chilumanxi/article/details/46363361
http://blog.csdn.net/chilumanxi/article/details/46317013
当然,队列也有自己的循环队列.在初始化建空队列的时候,我们令front = rear = 0,每当插入新的队列尾元素的时候,尾指针加一.每当删除头元素的时候,头指针加一,这样一来,头指针就可以始终指向第最先入队的元素.
那么问题最后就是如果队列已满的话,尾指针的下一位置就是头指针.下面写一下循环队列:
//-----------------循环队列---队列的顺序存储结构-------
#define MAXQSIZE 100 //最大队列长度
#define Status int
typedef struct{
QElemType *base; //初始化的动态分配存储空间
int front; //头指针,若队列不空,指向队列头元素
int rear; //尾指针,若队列不空,指向队列尾元素的下一个元素
}SqQueue;
//-----------------循环队列的基本操作的算法描述---------
Status InitQueue(SqQueue &Q){
//构造一个空队列Q
Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
if(!Q.base) exit(OVERFLOW);
Q.front = Q.rear = 0;
return OK;
}
int QueueLength(SqQueue Q){
//返回Q的元素个数,也就是队列的长度
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE //循环队列,所以求余
}
Status EnQueue(SqQueue &Q, QElemType e){
//输入元素e为Q的新的队尾元素
if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR; //队列满
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
return OK;
}
Status DeQueue(SqQueue &Q, QElemType &e){
//若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR
if(Q.front == Q.rear) return ERROR;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return OK;
}