一、队列的基本概念
队列是一种操作比较受限的线性表,因为它只允许在表的一段进行插入,而在表的另一端进行删除。遵行的是一个先进先出的原则。
二、队列的顺序存储结构
1.队列的顺序存储
队列的顺序存储也是跟栈和简单顺序表一样,在一开始需要定义元素存储的大小。之后设置两个指针,分别指向队头和队尾。队列的顺序存储类型为:
#define MaxSize 6 //定义队列中元素的最大个数
typedef int ElemType;
typedef struct {
ElemType data[MaxSize]; //只能存放MaxSize-1个元素
int front, rear; //定义一个队头指针和一个队尾指针
}SqQueue;
(1)在定义一个队列元素的最大个数之后,真正可以存储数据的只有MaxSize-1个元素,因为需要拿出一个存储单元来使队尾指针指向它,不然在判断队空还是队满的时候,队头指针和队尾指针都指向一个存储单元之后会导致判断不了,如图所示:
(2)当第一个元素入队时,队头指针就会一直指向它,除非它出队列了,而队尾指针则指向插入元素后的一个存储单元。每插入一个元素后,队尾指针都会向后移一个位置。而每当出队一个元素之后,队头指针也会往后移一个位置。
2.循环队列的操作
(1)初始化
//初始化
void InitQueue(SqQueue& Q)
{
Q.front = Q.rear = 0;
}
(2)判断队列是否为空
//判断队列是否为空
bool isEmpty(SqQueue Q)
{
if (Q.front == Q.rear) //当队头、队尾指针指向同一个存储单元时队列为空
{
return true;
}
return false;
}
(3)入队操作
//入队操作
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;
}
插入数据之后设置一个断点可以看到插入的相应值,分别是2,3,4,5。
(4)出队操作
//出队
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;
}
三、队列的链式存储结构
1.队列的链式存储
队列的链式又称为链队列,同时带有队头结点和队尾结点的单链表。
队列的链式存储结构类型为:
typedef int ElemType;
typedef struct LinkNode { //链式队列结点
ElemType data;
struct LinkNode* next;
}LinkNode;
typedef struct { //链式队列
LinkNode* front, * rear; //队列的队头和队尾指针
}LinkQueue;
2.链式存储的操作
(1)初始化
//初始化
void InitQueue(LinkQueue& Q)
{
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode)); //建立头结点
Q.front->next = NULL;
}
(2)判断队列是否为空
当队头结点等于队尾结点的时候,则队列为空。
//判断是否为空
bool InEmpty(LinkQueue Q)
{
if (Q.front == Q.rear)
return true;
else
return false;
}
(3)入队操作
//入队
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;
}
设置一个断点查看入队的元素,分别为2,3,4,5。
(4)出队操作
//出队
bool DeQueue(LinkQueue& Q, ElemType& x)
{
if (Q.front == Q.rear)
return false;
LinkNode* p = Q.front->next; //因为存在头结点,且头结点里面没数据,所以指向下一个
x = p->data;
Q.front->next = p->next;
if (Q.rear == p)
Q.rear = Q.front; //如果队里中只有一个结点,则出队之后队列变空
free(p);
return true;
}
四、完整代码
(1)队列的顺序存储
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 6 //定义队列中元素的最大个数
typedef int ElemType;
typedef struct {
ElemType data[MaxSize]; //只能存放MaxSize-1个元素
int front, rear; //定义一个队头指针和一个队尾指针
}SqQueue;
//初始化
void InitQueue(SqQueue& Q)
{
Q.front = Q.rear = 0;
}
//判断队列是否为空
bool isEmpty(SqQueue Q)
{
if (Q.front == Q.rear)
{
return true;
}
return false;
}
//入队操作
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;
}
int main()
{
SqQueue Q;
bool ret;
ElemType element;
InitQueue(Q);
EnQueue(Q, 2);
EnQueue(Q, 3);
EnQueue(Q, 4);
EnQueue(Q, 5);
EnQueue(Q, 6);
ret = EnQueue(Q, 7); //已经超出了范围,所以7入不了队
if (ret)
{
printf("入队成功\n");
}
else {
printf("入队失败\n");
}
ret = isEmpty(Q);
if (ret)
{
printf("队列为空\n");
}
else {
printf("队列不为空\n");
}
ret= DeQueue(Q, element);
if (ret)
{
printf("出队成功,元素值为%d\n",element);
}
else {
printf("出队失败:\n");
}
ret = DeQueue(Q, element);
if (ret)
{
printf("出队成功,元素值为%d\n", element);
}
else {
printf("出队失败:\n");
}
return 0;
}
(2)队列的链式存储
#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;
}
//判断是否为空
bool InEmpty(LinkQueue Q)
{
if (Q.front == Q.rear)
return true;
else
return false;
}
//入队
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;
}
//出队
bool DeQueue(LinkQueue& Q, ElemType& x)
{
if (Q.front == Q.rear)
return false;
LinkNode* p = Q.front->next; //因为存在头结点,且头结点里面没数据,所以指向下一个
x = p->data;
Q.front->next = p->next;
if (Q.rear == p)
Q.rear = Q.front; //如果队里中只有一个结点,则出队之后队列变空
free(p);
return true;
}
int main()
{
LinkQueue Q;
bool ret;
ElemType element;
InitQueue(Q);
EnQueue(Q, 2);
EnQueue(Q, 3);
EnQueue(Q, 4);
EnQueue(Q, 5);
ret = DeQueue(Q, element);
if (ret)
{
printf("出队成功,出队元素为:%d\n", element);
}
else
{
printf("出队失败\n");
}
ret = DeQueue(Q, element);
if (ret)
{
printf("出队成功,出队元素为:%d\n", element);
}
else
{
printf("出队失败\n");
}
return 0;
}