概述
1.先进先出的线性序列,称为队列,队列也是一种线性表,只不过它是操作受限的线性表,只能在两端操作。一端进,一端出。进的一端称为队尾,出的一端称为队头,队列可以用顺序存储也可以用链式存储。
2.队列的顺序存储形式,可以用一段连续的空间存储数据元素,用两个整型变量记录队头和队尾元素的下标。
3初始化
(1)
base为数组的基地址,front,base分别代表指向队头和队尾的"指针"(数组下标),构造空队列只需要申请一块内存给基地址,并且将队头指针与队尾指针赋值为0.
(2)
因为该队列为循环队列所以
typedef struct SqQueue
{
int* base;
int front, rear;
}SqQueue;
//构造空队列
bool InitQueue(SqQueue& Q)
{
Q.base = new int[Maxsize];
if (Q.base == NULL)
{
return false;
}
Q.front = Q.rear = 0;
return true;
}
4入队
(1)将队尾指向的位置赋值,并且赋值后将队尾的位置后移
(2)在入队时难免会出现以下情况
队列的空间未利用完,但是却造成了元素的溢出(又称"假溢出"),所以要利用循环队列,这样就不会有这样的顾虑
入队的操作为
Q.base[Q.rear]=e; 将元素e放入Q.rear指向的空间
Q.rear=(Q.rear+1)%Maxsize rear指针向后移动一个单位
至于为什么要加对(Q.rear+1)取模,这是因为rear指针会一直增加到比队列容量大的数字,对其取模就是为了使其缩小,指向真正的位置例如 容量大小为5 队尾指向9 取模队尾指向的是4,说明队尾指正已经走过了一个圈
tips:在入队前要判断队列是否为空怎们办
如图此时队尾指向的是循环队列的最后一个空间,这个空间并没有存放任何数据,判断队列是否为满只要将队尾指针+1看看其是否与队头相等,此处为什么要取模?
例如队列空间大小为10,队尾指向第10个空间,下标为9,对其加1等于10,取模等于0,此时队头也是指向0的所以需要取模
有例如如果一开始队头指向的是1,队尾指向的是0,那么队尾加1,取模后为1,那么此时对也满
//入队
bool Push(SqQueue& Q, int e)
{
if ((Q.rear + 1) % Maxsize == Q.front)
{
cout << "队满" << endl;
return false;
}
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % Maxsize;
return true;
}
5出队
出队前判断队列是否为空
当尾指针与头指针指向一起时队空,注意与队满的区别
出队的操作
e=Q.base[Q.front];
Q.front=[Q.front+1]%Maxsize;
将头指针向着元素增长方向移动一个单元,原来的头指针指向的元素并没有真正的删除,只是逻辑上的删除,后序如果要用到这个空间,会用新的元素将其覆盖掉
至于为什么要用取模和上述的入队是一致的
bool Pop(SqQueue& Q, int& e)
{
if (Q.rear == Q.front)
{
cout << "队空" << endl;
return false;
}
e = Q.base[Q.front];
Q.front = (Q.front + 1) % Maxsize;
return true;
}
6.获取队头元素
判断队列是否为空
简单的数组取元素而已
int Get_front(SqQueue Q)
{
if (Q.rear == Q.front)
{
cout << "队空" << endl;
return -1;
}
return Q.base[Q.front];
}
7.获取队尾元素
判断队列是否为空
因为队尾一直指向最后一个元素的后一个位置,所以要去指正前面的空间,就是队尾元素
int Get_back(SqQueue Q)
{
if (Q.front == Q.rear)
{
cout << "队空" << endl;
return -1;
}
return Q.base[Q.rear - 1];
}
8.获取队列元素个数
这两段的代码意思是一样的
因为队尾减队头可能会出现负数,所以需要加上容量大小后取模,这样才会得到真实的容量大小
例如队列大小6,队尾指向1,队头指向2,那么元素个数为(1-2+6)%6=5个
例如队列大小6,队尾指向5,队头指向0,那么元素个数为(5-0+6)%6=5个
int length(SqQueue Q)
{
return (Q.rear - Q.front + MaxSize) % MaxSize;
/*if (Q.rear - Q.front >= 0)
{
return Q.rear - Q.front;
}
else
{
return (Q.rear - Q.front + MaxSize);
}*/
}
完整代码如下
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
using namespace std;
const int MaxSize = 100;
typedef struct SqQueue
{
int* base;
int front, rear;
}SqQueue;
bool InitQueue(SqQueue& Q)
{
Q.base = new int[MaxSize];
if (Q.base == NULL)
{
return false;
}
Q.front = Q.rear = 0;
return true;
}
bool Push(SqQueue& Q, int e)
{
if ((Q.rear + 1) % MaxSize == Q.front)
{
return false;
}
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MaxSize;
return true;
}
bool Pop(SqQueue& Q, int& e)
{
if (Q.rear == Q.front)
{
return false;
}
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MaxSize;
}
int Get_front(SqQueue Q)
{
if (Q.front == Q.rear)
{
return -1;
}
return Q.base[Q.front];
}
int Get_back(SqQueue Q)
{
if (Q.front == Q.rear)
{
return -1;
}
return Q.base[Q.rear - 1];
}
int length(SqQueue Q)
{
return (Q.rear - Q.front + MaxSize) % MaxSize;
/*if (Q.rear - Q.front >= 0)
{
return Q.rear - Q.front;
}
else
{
return (Q.rear - Q.front + MaxSize);
}*/
}
int main()
{
SqQueue S;
InitQueue(S);
int n = 0;
cout << "请输入有多少元素" << endl;
cin >> n;
cout << "依次输入元素" << endl;
while (n--)
{
int e;
cin >> e;
Push(S, e);
}
int L = length(S);
for (int i = 0; i < L; i++)
{
cout << "队尾:"<<Get_back(S) << " "<<"队头:"<<Get_front(S)<<"---";
int e = 0;
Pop(S, e);
cout << e <<" ";
cout << endl;
}
//cout << length(S);
cout << endl;
system("pause");
return EXIT_SUCCESS;
}