定义
与栈不同,队列的两端都允许插入和删除操作。
队列(Queue) 是只允许一端进行插入操作,而另一端进行删除操作的线性表。
相关术语
队头:允许删除的一端
队尾:允许插入的一端
空队列:无元素
特点:先进先出
基本操作
- InitQueue(&Q) 初始化队列, 构造一个空队列Q
- DestroyQueue(&Q) 销毁队列, 释放Q占用的内存空间
- EnQueue(&Q, x) 入队, 若队列Q未满, 则将x加入, 使之成为新的队尾
- DeQueue(&Q, &x) 出队, 若队列Q非空, 则删除Q的队头元素, 并用x返回
- GetHead(Q, &x) 读队头元素, 若队列Q非空, 则将队头元素赋值给x
- QueueEmpty(Q) 判断队列是否为空, 若队列Q为空, 则返回true, 否则返回false
队列的顺序实现
//Power by Marscode
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
typedef struct{
ElemType data[MAXSIZE];
int front, rear;//队头指针和队尾指针
}SqQueue;
//使用
void testQueue(){
SqQueue Q;
//.......
}
//初始化时,队头和队尾指针都指向0
void InitQueue(SqQueue &Q){
Q.front = Q.rear = 0;
}
//销毁
void DestroyQueue(SqQueue &Q){
free(Q.data);
Q.front = Q.rear = 0;
}
bool GetHead(SqQueue Q, ElemType &x){
if(Q.front == Q.rear){
return false;
}//队空,报错
x = Q.data[Q.front];//出队
return true;
}
//入队
bool EnQueue(SqQueue &Q, ElemType x){
if ((Q.rear + 1) % MAXSIZE == Q.front){
return false;
}//队满,报错
Q.data[Q.rear] = x;//入队
Q.rear = (Q.rear + 1) % MAXSIZE;//队尾指针加1
return true;
}
//出队
bool DeQueue(SqQueue &Q, ElemType &x){
if(Q.front == Q.rear){
return false;
}//队空,报错
x = Q.data[Q.front];//出队
Q.front = (Q.front + 1) % MAXSIZE;//队头指针加1
//和栈的出栈相似,不需要真的删除元素,只需要逻辑上的出队
return true;
}
循环队列
Q.data[Q.rear] = x;//入队
Q.rear = (Q.rear + 1) % MAXSIZE;//队尾指针加1
链式队列
链式队列分为两种:带头指针和不带头指针。
- 带头指针的链式队列,头指针指向头结点,头结点的指针指向队头元素,尾结点的指针指向队尾元素。
- 不带头指针的链式队列,头指针和尾指针都指向队头元素。
//Power by Marscode
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
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;
}
void EnQueue(LinkQueue &Q, ElemType x){
//申请新结点
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;//新结点插入到队尾
Q.rear = s;//队尾指针指向新结点
return true;
}
//出队
bool DeQueue(LinkQueue &Q, ElemType &x){
if(Q.front == Q.rear){
return false;
}//队空,报错
LinkNode *p = Q.front->next;//p指向队头元素
x = p->data;//出队
Q.front->next = p->next;//头结点的指针指向队头元素的下一个元素
if(Q.rear == p){//如果队头元素是队尾元素
Q.rear = Q.front;//队尾指针指向头结点
}
free(p);
return true;
}
//销毁
void DestroyQueue(LinkQueue &Q){
while(Q.front!= NULL){
Q.rear = Q.front->next;//队尾指针指向头结点的下一个元素
free(Q.front);//释放头结点
Q.front = Q.rear;//队头指针指向队尾指针
}
}
Comments