1.顺序队
队列的特性:
- 先进先出,后进后出。
- 后进后出,先进先出。😋
图解:
代码:
(1)队列的数据结构
const int MAXSIZE = 100; //规定队列元素的大小
typedef int ElemType;
typedef struct SqQueue
{
ElemType data[MAXSIZE]; //队列元素的数据类型
int front, rear; //两个指针,front指向队头,rear指向队尾
}SqQueue; //SqQueue是struct SqQueue的别名
(2)初始化
void Initail_Squeue(SqQueue *&sq) //初始化
{
sq = new SqQueue;
memset(sq->data, 0, sizeof(sq->data));
sq->rear = sq->front = -1;
}
(3)入队
bool Push(SqQueue* sq, int e) //e是入队元素
{
if(sq->front == MAXSIZE - 1) //队满
return false;
else
{
sq->front++;
sq->data[sq->front] = e;
return true;
}
}
(4)出队
bool Pop(SqQueue* sq,int &e) //出队,注意这里的e是引用,为什么呢?这样既可以使函数是bool类型使代码简洁,又可以间接返回一个出
//队的值,相当于返回类型为int类型的函数
{
if (sq->front == sq->rear) //队空
return false;
else
{
sq->front--;
e = sq->data[sq->front];
return true;
}
}
(5)输出
void Print(SqQueue *sq)
{
if (sq->front == sq->rear)
cout << "队空!没有元素!\n";
else
{
while (sq->front != sq->rear)
{
cout << sq->data[sq->front] << " ";
sq->front--;
}
cout << endl;
return;
}
}
所有代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<new>
using namespace std;
const int MAXSIZE = 100; //规定队列元素的大小
typedef int ElemType;
typedef struct SqQueue
{
ElemType data[MAXSIZE]; //队列元素的数据类型
int front, rear; //两个指针,front指向队头,rear指向队尾
}SqQueue; //SqQueue是struct SqQueue的别名
void Initail_Squeue(SqQueue *&sq) //初始化
{
sq = new SqQueue;
memset(sq->data, 0, sizeof(sq->data));
sq->rear = sq->front = -1;
}
bool Push(SqQueue* sq, int e) //e是入队元素
{
if(sq->front == MAXSIZE - 1) //队满
return false;
else
{
sq->front++;
sq->data[sq->front] = e;
return true;
}
}
bool Pop(SqQueue* sq,int &e) //出队,注意这里的e是引用,为什么呢?这样既可以使函数是bool类型使代码简洁,又可以间接返回一个出
//队的值,相当于返回类型为int类型的函数
{
if (sq->front == sq->rear) //队空
return false;
else
{
e = sq->data[sq->front];
sq->front--;
return true;
}
}
void Print(SqQueue *sq)
{
if (sq->front == sq->rear)
cout << "队空!没有元素!\n";
else
{
int k = sq->front;
while (k != sq->rear)
{
cout << sq->data[k] << " ";
k--;
}
cout << endl;
return;
}
}
int main()
{
SqQueue* sq;
//第一步:初始队列
Initail_Squeue(sq);
//第二步:开始队列的操作:
int choice;
cout << "选项:(1)入队 (2)出队 (3)输出 (4)退出\n";
cout << "输出你的选项:";
cin >> choice;
int e;
while (choice)
{
switch (choice)
{
case 1:
{
cout << "输入入队元素:";
cin >> e;
if (Push(sq, e))
cout << "入队成功!\n";
else
cout << "入队失败,队满!\n";
break;
}
case 2:
{
if (Pop(sq,e))
cout << "出队元素是:" << e << endl;
else
cout << "队空!\n";
break;
}
case 3:
{
cout << "输出队列所有元素:\n";
Print(sq);
break;
}
case 4:
{
return 0;
}
default:
{
cout << "输出错误!重新输入:\n";
break;
}
}
cout << "选项:(1)入队 (2)出队 (3)输出 (4)退出\n";
cout << "输出你的选项:";
cin >> choice;
}
return 0;
}
2.链队
#include<iostream>
#include<cstring>
using namespace std;
typedef int ElemType;
typedef struct Qnode
{
ElemType data;
struct Qnode* next;
}Qnode,*Qptr;
typedef struct
{
Qnode* front;
Qnode* rear;
}LinkQueue;
void InitQueue(LinkQueue& Q) //初始化
{
Q.front = Q.rear = new Qnode; //使队头和队尾都指向一个新的节点,这个节点为头节点
Q.front->next = NULL;
}
void EnQueue(LinkQueue& Q, int e) //入队操作
{
Qptr s;
s = new Qnode;
s->data = e;
s->next = NULL;
Q.rear->next = s; //新节点插入队尾
Q.rear = s; //队尾后移 ,这和顺序队的写法不一样,顺序队是队头移动,链队是队尾移动。但是本质上都是先进先出。
}
bool DeQueue(LinkQueue& Q, int& e) //出队
{
if (Q.front == Q.rear) //没有元素直接返回
return false;
Qptr p = Q.front->next;//p指向队头的下一个节点,也就是头节点的下一个节点,也就是真正意义上队列的第一个元素
e = p->data; //记录出队的值
Q.front->next = p->next;//使队列第一个元素指向出队元素的下一个元素,也就是新的“队头元素”
if (p == Q.rear)//说明队列只有一个元素,出队后一个元素都没有了
Q.rear = Q.front;
p->next = NULL;
delete p; //最后删除出队节点
return true;
}
int GetHead(LinkQueue Q) //取队头元素
{
if (Q.front != Q.rear)
return Q.front->next->data;
return -1;
}
int main()
{
LinkQueue Q;
int n, x;
InitQueue(Q);//初始化队列(一定要初始化,否则后面存储出错)
cout << "请输入元素个数n:" << endl;
cin >> n;
cout << "请依次输入n个整型数,依次入队:" << endl;
while (n--) {
cin >> x;
EnQueue(Q, x);//入队
}
cout << "队头元素:" << GetHead(Q) << endl;
cout << "元素依次出队:" << endl;
while (true) {//如果栈不空,则依次出栈
if (DeQueue(Q, x))
cout << x << "\t";//出队元素
else
break;
}
cout << endl;
return 0;
}
3.循环队列
入队操作如图所示,先将元素放入Q.rear指向的空间,然后Q.rear向后移动一个单位.
当然会出现一个问题,因为front和rear是不停移动的,所以每次+1的话可能会造成数组越界。那么可以用求余的方法来做.
Q.base[Q.rear]=x; //不用担心这里Q.rear越界,因为在这个x放入之前,已经对Q.rear取余了。
Q.rear=(Q.rear+1)%Maxsize;
出队就更简单了,每次将Q.front往后移动一个单位
e=Q.base[Q.front];
Q.front=(Q.front+1)%Maxsize;
那么我认为循环队列最难的问题就是求队列中元素的个数,当然,用一个for循环遍历队列肯定可以,但是这样就很慢,可以通过数学的方法来求得是最好的。
求队列中元素的个数
使用front和rear的相对位置,front和rear由于进行了求余处理,所以他们的值的范围都是[0,Maxsize-1]
这个时候就有两种情况:
- rear>=front
- rear<=front
int k=0;
if(Q.rear>=Q.front)
k=Q.rear-Q.front;
if(Q.rear<=Q.front)
k=Maxsize-(Q.front-Q.rear);
下面是代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef int ElemType;
const int MaxSize = 100;
typedef struct SqQueue
{
int rear, front;
ElemType *base;
}SqQueue;
bool InitQueue(SqQueue& Q) //初始化
{
Q.base = new int[MaxSize]; //分配空间
if (!Q.base) //如果空间分配不成功,返回false;
return false;
Q.front = Q.rear = 0;
return true;
}
bool EnQueue(SqQueue& Q, int e) //入队
{
if ((Q.rear + 1) % MaxSize == Q.rear) //队满的情况
return false;
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MaxSize;
return true;
}
bool DeQueue(SqQueue& Q, int& e) //出队
{
if (Q.front == Q.rear) //队空
return false;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MaxSize;
return true;
}
void Print(SqQueue& Q) //输出队列元素
{
if (Q.front == Q.rear)
cout << "没有元素!\n";
else
{
cout << "输出所有元素:\n";
if (Q.front >= Q.rear)
{
int k = Q.front;
int i = 1;
for (k; i <= (MaxSize - (Q.front - Q.rear)); k = (k + 1) % MaxSize)
{
cout << Q.base[k] << " ";
i++;
}
cout << endl;
}
if (Q.front <= Q.rear)
{
int k = Q.front;
int i = 1;
for (k;i<=Q.rear-Q.front ; k = (k + 1) % MaxSize)
{
cout << Q.base[k] << " ";
i++;
}
cout << endl;
}
}
}
int main()
{
SqQueue Q;
InitQueue(Q);
int choice;
cout << "选项:(1)入队 (2)出队 (3)输出 (4)退出\n";
cout << "输出你的选项:";
cin >> choice;
int e;
while (choice)
{
switch (choice)
{
case 1:
{
cout << "输入入队元素:";
cin >> e;
if (EnQueue(Q, e))
cout << "入队成功!\n";
else
cout << "入队失败,队满!\n";
break;
}
case 2:
{
if (DeQueue(Q, e))
cout << "出队元素是:" << e << endl;
else
cout << "队空!\n";
break;
}
case 3:
{
cout << "输出队列所有元素:\n";
Print(Q);
break;
}
case 4:
{
return 0;
}
default:
{
cout << "输出错误!重新输入:\n";
break;
}
}
cout << "选项:(1)入队 (2)出队 (3)输出 (4)退出\n";
cout << "输出你的选项:";
cin >> choice;
}
return 0;
}