目录
一、顺序队列
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。
二、操作
2.1、初始化
#define MaxSize 10
typedef struct
{
int data[MaxSize]; //静态数组存放队列元素
int front, rear; //队头指针和队尾指针
}SqQueue;
//初始化队列
void InitQueue(SqQueue &Q)
{
//初始化时 队头、队尾指针都指向0
Q.front = Q.rear = 0;
}
2.2、 入队
//入队操作
bool EnQueue(SqQueue& Q)
{
int n, x;
cout << "请输入入队元素个数" << endl;
cin >> n;
while (1)
{
if (n > MaxSize)
{
cout << "队列超载,请重新输入..." << endl;
cin >> n;
}
else
{
break;
}
}
if ((Q.rear + 1) % MaxSize == Q.front)
{
return false;
}
for (int i = 0; i < n; i++)
{
cout << "请输入第"<<i+1<<"个入队元素" << endl;
cin >> x;
Q.data[Q.rear] = x; //将x插入队尾
Q.rear = (Q.rear + 1) % MaxSize; //队尾指针加1取模
}
return true;
}
2.3、出队
//出队操作
bool DeQueue(SqQueue& Q,int &x)
{
if (Q.rear == Q.front)
{
return false; //对空则报错
}
int n;
cout << "请输入出队元素个数" << endl;
cin >> n;
while (1)
{
if (n > Q.rear)
{
cout << "出队元素个数超过现有个数,请重新输入..." << endl;
cin >> n;
}
else
{
break;
}
}
for (int i = 0; i < n; i++)
{
x = Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;
}
return true;
}
上一步的入队操作和这一步的出队操作,在给Q.front和Q.rear赋值的时候我们都用到了%(取余)这样做的原因是可以让队列形成一个闭环,这样在入队和出队操作同时进行时我们可以不至于在最后一个元素入队后,前面的元素出队,可以让rear重新回到0号位置继续做入队操作。
2.4、获取对头元素
//获取对头元素的值,用x返回
bool GetHead(SqQueue Q, int& x)
{
if (Q.rear == Q.front)
{
return false;
}
x = Q.data[Q.front];
cout << "对头元素为" << x << endl;
return true;
2.5、判空操作与打印顺序队列操作
//判断队列是否为空
bool QueueEmpty(SqQueue Q)
{
if (Q.rear == Q.front) //队空条件
{
cout << "对空" << endl;
return true;
}
else
{
cout << "对不空" << endl;
return false;
}
}
//打印
void PrintSqQueue(SqQueue Q)
{
cout << "此时顺序队列为" << endl;
int g = (Q.rear + MaxSize - Q.front) % MaxSize;//记录队列元素个数
for (int i = Q.front; i < g+Q.front; i++)
{
cout << Q.data[i] << " ";
}
cout << endl ;
}
队列元素的计算公式需要自己推敲一下
三、完整代码
#include<iostream>
using namespace std;
#define MaxSize 10
typedef struct
{
int data[MaxSize]; //静态数组存放队列元素
int front, rear; //队头指针和队尾指针
}SqQueue;
//初始化队列
void InitQueue(SqQueue &Q)
{
//初始化时 队头、队尾指针都指向0
Q.front = Q.rear = 0;
}
//判断队列是否为空
bool QueueEmpty(SqQueue Q)
{
if (Q.rear == Q.front) //队空条件
{
cout << "对空" << endl;
return true;
}
else
{
cout << "对不空" << endl;
return false;
}
}
//入队操作
bool EnQueue(SqQueue& Q)
{
int n, x;
cout << "请输入入队元素个数" << endl;
cin >> n;
while (1)
{
if (n > MaxSize)
{
cout << "队列超载,请重新输入..." << endl;
cin >> n;
}
else
{
break;
}
}
if ((Q.rear + 1) % MaxSize == Q.front)
{
return false;
}
for (int i = 0; i < n; i++)
{
cout << "请输入第"<<i+1<<"个入队元素" << endl;
cin >> x;
Q.data[Q.rear] = x; //将x插入队尾
Q.rear = (Q.rear + 1) % MaxSize; //队尾指针加1取模
}
return true;
}
//出队操作
bool DeQueue(SqQueue& Q,int &x)
{
if (Q.rear == Q.front)
{
return false; //对空则报错
}
int n;
cout << "请输入出队元素个数" << endl;
cin >> n;
while (1)
{
if (n > Q.rear)
{
cout << "出队元素个数超过现有个数,请重新输入..." << endl;
cin >> n;
}
else
{
break;
}
}
for (int i = 0; i < n; i++)
{
x = Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;
}
return true;
}
//获取对头元素的值,用x返回
bool GetHead(SqQueue Q, int& x)
{
if (Q.rear == Q.front)
{
return false;
}
x = Q.data[Q.front];
cout << "对头元素为" << x << endl;
return true;
}
//打印
void PrintSqQueue(SqQueue Q)
{
cout << "此时顺序队列为" << endl;
int g = (Q.rear + MaxSize - Q.front) % MaxSize;//记录队列元素个数
for (int i = Q.front; i < g+Q.front; i++)
{
cout << Q.data[i] << " ";
}
cout << endl ;
}
int main()
{
int x;
SqQueue Q;
InitQueue(Q); //初始化
EnQueue(Q); //入队
PrintSqQueue(Q); //打印
GetHead(Q,x); //获取对头元素
DeQueue(Q, x); //出队
PrintSqQueue(Q); //打印
GetHead(Q, x); //获取对头元素
system("pause");
return 0;
}
最后,我们可以看一看运行的具体效果
四、链式队列
链式队列其实就是单链表,我们单链表掌握好的情况下,链式队列也不成问题,里面没有什么特殊的知识点,所以不再赘述,直接把代码打在下面,有不懂的地方欢迎评论区讨论
#include<iostream>
using namespace std;
struct LinkNode
{
int data; //数据域
struct LinkNode* next; //指针域
};
typedef struct //链式队列
{
LinkNode* front, * rear; //队列的队头和队尾指针
}LinkQueue;
//初始化队列(带头结点)
void InitQueue(LinkQueue& Q)
{
//初始时 front,rear都指向头结点
Q.front = Q.rear = new LinkNode();
Q.front->next = NULL;
}
//判断是否为空
bool IsEmpty(LinkQueue Q)
{
if (Q.front == Q.rear)
{
cout << "队列为空" << endl;
return true;
}
else
{
cout << "队列不为空" << endl;
return false;
}
}
//新元素入队(带头节点)
void EnQueue(LinkQueue& Q)
{
int n,x;
cout << "请输入入队元素个数" << endl;
cin >> n;
for (int i = 0; i < n; i++)
{
cout << "请输入第" << i + 1 << "个入队元素" << endl;
cin >> x;
LinkNode* s = new LinkNode();
s->data = x;
s->next = NULL;
Q.rear->next = s; //新节点插入到rear之后
Q.rear = s;
}
cout << "新元素入队完成!" << endl;
}
//队头元素出队
bool DeQueue(LinkQueue& Q)
{
int n,x;
if (Q.front == Q.rear)
{
return false;
}
cout << "请输入出队元素个数" << endl;
cin >> n;
for (int i = 0; i < n; i++)
{
LinkNode* p = Q.front->next;
x = p->data; //用变量x返回队头元素
Q.front->next = p->next; //修改头结点的next指针
if (Q.rear == p) //此次是最后一个节点出队
{
Q.rear = Q.front; //修改rear指针
}
delete p;
}
return true;
}
//获取队头元素
bool GetHead(LinkQueue Q)
{
if (Q.rear == Q.front)
{
return false;
}
int x;
x = Q.front->next->data;
cout << "队头元素为" << x << endl;
return true;
}
//打印操作
void PrintLinkQueue(LinkQueue Q)
{
cout << "当前单链表为" << endl;
while (Q.front->next) {
cout << Q.front->next->data << " ";
Q.front = Q.front->next;
}
cout << endl;
}
int main()
{
LinkQueue Q;
InitQueue(Q);
EnQueue(Q);
PrintLinkQueue(Q);
GetHead(Q);
DeQueue(Q);
PrintLinkQueue(Q);
system("pause");
return 0;
}