文字描述
队列是和栈相反,队列是一种先进先出(first in first out,缩写FIFO)的线性表,它只允许在表的一端进行插入,而在另一端进行删除。和生活中的排队相似,最早进入队列的元素最早离开。在队列中,允许插入的一端加队尾,允许删除的一端叫队头。
另外除了栈和队列,还有一种限定性数据结构是双端队列,它是一种插入和删除操作在表的两端进行的线性表。可以用一个铁道铁轨网络来比喻双端队列。
示意图
表示和实现
A 链队列(链式表示)
用链表表示的队列简称链队列。一个链队列需要分别指向队头和队为的指针才能唯一确定。一般,为了操作方便,会给链队列添加一个不存数据的头结点,并令头结点的next指针指向头结点。由此,空的链队列的判决条件为头指针和尾指针均指向头结点。
代码实现
//
// Created by lady on 19-4-4.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef struct QElemType{
char data[];
}QElemType; typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode, *QueuePtr;
typedef struct LinkQueue{
QueuePtr front;
QueuePtr rear;
}LinkQueue; static int InitQueue(LinkQueue *Q);
static int CreateQueue(LinkQueue *Q, int n);
static int DestoryQueue(LinkQueue *Q);
static int EnQueue(LinkQueue *Q, QElemType e);
static int DeQueue(LinkQueue *Q, QElemType *e);
static int QueueTraverse(LinkQueue Q); int main(int argc, char *argv[])
{
LinkQueue Q;
int i = ;
if(CreateQueue(&Q, )<){
return -;
}
printf("依次出队列!\n");
QElemType e;
while(!DeQueue(&Q, &e)){
printf("%s\n", e.data);
}
printf("销毁队列!\n");
DestoryQueue(&Q);
return ;
} static int InitQueue(LinkQueue *Q)
{
if(Q == NULL){
return -;
}
Q->front = (QueuePtr)malloc(sizeof(QNode));
Q->front->next = NULL;
Q->rear = Q->front;
if(Q->front == NULL){
return -;
}else{
return ;
}
} static int CreateQueue(LinkQueue *Q, int n)
{
printf("创建一个长度为%d,以链式存储的链队列!\n", n);
if(InitQueue(Q)<){
return -;
}
int i = ;
QElemType e;
for(i=; i<n; i++){
printf("输入第%d个元素:", i+);
scanf("%s[^\\n]", e.data);
if(EnQueue(Q, e)<){
return -;
}
}
return ;
} static int DestoryQueue(LinkQueue *Q)
{
QueuePtr p = Q->front->next;
QueuePtr q = NULL;
while(p){
q = p;
p = p->next;
free(q);
}
if(Q->front){
free(Q->front);
Q->front = NULL;
}
return ;
}
static int EnQueue(LinkQueue *Q, QElemType e)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
if(p == NULL){
return -;
}
p->data = e;
p->next = NULL;
Q->rear->next = p;
Q->rear = p;
return ;
} static int DeQueue(LinkQueue *Q, QElemType *e)
{
if(Q->front == Q->rear){
return -;
}
QueuePtr p = Q->front->next;
(*e) = p->data;
Q->front->next = p->next;
if(p == Q->rear){
Q->rear = Q->front;
}
free(p);
return ;
} static int QueueTraverse(LinkQueue Q)
{
QueuePtr p = Q.front->next;
while(p){
printf("%s\n", p->data.data);
p = p->next;
}
return ;
}
链队列
代码运行
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
创建一个长度为5,以链式存储的链队列!
输入第1个元素:a1
输入第2个元素:a2
输入第3个元素:a3
输入第4个元素:a4
输入第5个元素:a5
依次出队列!
a1
a2
a3
a4
a5
销毁队列! Process finished with exit code 0
B 循环队列(顺序表示)
和顺序栈类似,除了用一组地址连续的存储单元依次存放从队头到队尾的元素外,需设两个指针front和rear分别指向队头元素和队尾元素的位置。一般,为了充分利用空间,会将顺序队列设置为循环模式。在循环队列中,判断队列空间是否为”空“还是”满”。可有两种处理方法:1)单独设置一个标志位以区分队列是否为满 2)少用一个元素空间,约定以”队列头指针在队列指针的下一位置(指环状的下一个位置)上”作为队列满状态的标志。
代码实现
//
// Created by lady on 19-4-4.
// #include <stdio.h>
#include <stdlib.h>
#include <string.h> //----循环队列----队列的顺序存储结构
#define MAXQSIZE 6 //循环队列的最大长度
typedef struct QElemType{
char s[];
}QElemType;
typedef struct SqQueue{
QElemType *base;//初始化的动态分配存储空间
int front; //头指针,队列不为空的话指向队列头元素
int rear; //尾指针,队列不为空的话指向队列尾元素的下一个位置
}SqQueue; //初始化队列
static int InitQueue(SqQueue *Q);
//求队列长度
static int QueueLength(SqQueue Q);
//入队列
static int EnQueue(SqQueue *Q, QElemType e);
//出队列
static int DeQueue(SqQueue *Q, QElemType *e);
//遍历队列
static int TraverseQueue(SqQueue Q); static int CreateQueue(SqQueue *Q, int l){
if(InitQueue(Q) < ){
return ;
}
printf("创建一个长度为%d的顺序存储的循环队列\n", l); QElemType e;
int i = ;
for(i=; i<l; i++){
printf("输入第(%d)个数据元素:", i+);
memset(e.s, , sizeof(e.s));
scanf("%s[^\\n]", e.s);
EnQueue(Q, e);
}
return ;
} int main(int argc, char *argv[])
{
QElemType e;
SqQueue Q;
if(CreateQueue(&Q, ) < ){
return -;
}
printf("队列长度为%d\n", QueueLength(Q));
TraverseQueue(Q); snprintf(e.s, sizeof(e.s), "%s", "A6");
EnQueue(&Q, e); DeQueue(&Q, &e);
DeQueue(&Q, &e); snprintf(e.s, sizeof(e.s), "%s", "A6");
EnQueue(&Q, e); TraverseQueue(Q);
return ;
} static int InitQueue(SqQueue *Q)
{
Q->base = (QElemType *)malloc(MAXQSIZE*sizeof(QElemType));
if(!Q->base){
return -;
}else{
printf("队列初始化成功,队列可保存的最大元素个数为%d\n", MAXQSIZE);
Q->front = Q->rear = ;
return ;
}
} static int QueueLength(SqQueue Q)
{
return ((Q.rear-Q.front+MAXQSIZE) % MAXQSIZE);
} static int EnQueue(SqQueue *Q, QElemType e)
{
if((Q->rear+) % MAXQSIZE == Q->front){
printf("队列已满,元素%s不能入队列!\n", e.s);
return -;
}
printf("元素%s入队列!\n", e.s);
Q->base[Q->rear] = e;
Q->rear = (Q->rear+) % MAXQSIZE;
return ;
} static int DeQueue(SqQueue *Q, QElemType *e)
{
if(Q->front == Q->rear){
return -;
}
(*e) = Q->base[Q->front];
printf("元素%d:%s出队列!\n", Q->front, (*e).s);
Q->front = (Q->front+) % MAXQSIZE;
return ;
} static int TraverseQueue(SqQueue Q)
{
printf("遍历:");
if(Q.rear == Q.front){
printf("队列是空的\n");
}
int i = Q.front;
do{
printf("%d:%s ", i, Q.base[i].s);
i = (i+)%MAXQSIZE;
if(i == Q.rear){
break;
}
}while();
printf("\n");
}
循环队列
代码运行
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled
队列初始化成功,队列可保存的最大元素个数为6
创建一个长度为5的顺序存储的循环队列
输入第(1)个数据元素:a1
元素a1入队列!
输入第(2)个数据元素:a2
元素a2入队列!
输入第(3)个数据元素:a3
元素a3入队列!
输入第(4)个数据元素:a4
元素a4入队列!
输入第(5)个数据元素:a5
元素a5入队列!
队列长度为5
遍历:0:a1 1:a2 2:a3 3:a4 4:a5
队列已满,元素A6不能入队列!
元素0:a1出队列!
元素1:a2出队列!
元素A6入队列!
遍历:2:a3 3:a4 4:a5 5:A6 Process finished with exit code 0