1、队列定义
队列(Queue),允许一端进行插入,另一端进行删除,向队列中插入元素称为入队,删除元素成为我出队(First In First Out,简称FIFO)
队头,允许删除的一端,
队尾,允许插入的一端
2、循环队列
存储结构
# define MaxSize 5
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
【注】数组,最大存储MaxSize-1个元素
队满:( Q.rear + 1 ) % MaxSize == Q.front
改变队尾标记:Q.rear=(Q.rear+1)%MaxSize
步骤:
1.初始化循环队列(front,rear 赋值 0)
2.判断循环队列是否为空
3.入队、出队
代码实现:
#include <stdio.h>
#include <stdlib.h>
// 循环队列
#define MaxSize 5
typedef int ElemType;
typedef struct {
ElemType data[MaxSize]; // 数组,存储MaxSize-1个元素
int front, rear; // 队列头,队列尾
} SqQueue;
// 初始化循环队列
void initSqQueue(SqQueue &Q){
Q.front=Q.rear=0;
}
// 判断队列是否为空
bool isEmpty(SqQueue Q){
return Q.rear==Q.front? true: false;
}
// 入队操作
bool EnQueue(SqQueue &Q, ElemType value){
// 判断队列是否满了
if ((Q.rear+1)%MaxSize==Q.front){
return false;
}
Q.data[Q.rear]=value;
Q.rear=(Q.rear+1)%MaxSize; // 如果大于数组最大下标回到开头
return true;
}
// 出队操作
bool DeQueue(SqQueue &Q, ElemType &value){
if (isEmpty(Q)){
return false; // 队列为空无法出队
}
value=Q.data[Q.front]; // 头部出队
Q.front=(Q.front+1)%MaxSize;
return true;
}
int main() {
SqQueue Q; // 定义变量
// 初始化循环队列
initSqQueue(Q);
bool ret=isEmpty(Q); // 验证队列是否为空
if(ret){
printf("SqQueue is empty\n");
} else{
printf("SqQueue isn't empty\n");
}
bool result;
int arr[MaxSize]={3,4,5,6,7};
for (int i = 0; i < MaxSize; ++i) {
result= EnQueue(Q,arr[i]);
if(result){
printf("EnQueue success\n");
} else{
printf("EnQueue failed\n");
}
}
// 出队
ElemType element; // 存储出队元素
bool res=DeQueue(Q,element);
if (res){
printf("DeQueue success element=%d\n",element);
} else{
printf("DeQueue failed\n");
}
EnQueue(Q, 8);
return 0;
}
3、队列链式存储:
队列链式表示称为链队列,实际上是带有对头指针和的为指针的单链表。 头指针指向头结点,位置在指向尾结点。
存储结构
typedef int ElemTpye;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode; // 链表结点的结构体
typedef struct{
LinkNode *front,*rear; //链表头 链表尾
}LinkQueue;
LinkQueue Q;
相对于原有编写的链表增加了尾指针
初始化队列–入队–出队
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
// 链表结点结构体
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct {
LinkNode *front, *rear; // 链表头和链表尾
}LinkQueue;
// 队列初始化使用带头结点的链表来标识
void initQueue(LinkQueue &Q){
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode)); //链表头和链表尾指向同一个结点
Q.front->next=NULL; // 头结点的next指针为NULL
}
// 判断队列是否为空
bool isEmpty(LinkQueue Q){
if (Q.front==Q.rear){
return true;
} else{
return false;
}
}
// 入队
void EnQueue(LinkQueue &Q, ElemType value){
LinkNode *p=(LinkNode*)malloc(sizeof(LinkNode));
p->data=value;
p->next=NULL; //要让next为NULL
Q.rear->next=p; //尾指针的next指向p,从尾部入队;
Q.rear=p; //rear指向新的尾部
}
bool DeQueue(LinkQueue &Q, ElemType &value){
if (isEmpty(Q)){
return false; //队列为空
}
LinkNode *q=Q.front->next; //拿到第一个结点,存入q
value=q->data;
Q.front->next=q->next;
// 链表只剩余一个结点时,被删除后要改变rear
if (Q.rear==q){
Q.rear=Q.front;
}
free(q); // 断链
return true;
}
int main() {
LinkQueue Q;
initQueue(Q); //使用带头结点的链表
EnQueue(Q,3);
EnQueue(Q,4);
EnQueue(Q,5);
EnQueue(Q,6);
EnQueue(Q,7);
ElemType element;
bool ret=DeQueue(Q, element);
if (ret){
printf("DeQueue success element=%d\n", element);
} else{
printf("DeQueue failed\n");
}
return 0;
}