讲四种实现
(普通数组模拟队列实现不讲,很轻便也很实用,不难自己随意写写就行)
循环队列(Circular queue)
队列和栈在使用时,即使操作数很多,但一般实时存储在其中的数据并不多,于是我们采用循环队列的方式来节省空间。
那循环队列其实就是,当队列中申请好的连续空间中已经填满数据时(并不是指队列已满,队列是只夹在front和rear之间的数据,包括front不包括rear)又从这段空间的开头开始覆盖存储。
那要注意的几个点就是
- 如何判队列空
- 如何判队列已满
- 如何计算队长
以上问题有相应公式
https://www.jianshu.com/p/9ba8a65464dd这里有详细图解
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef int ElementType;
typedef struct Circular
{
int Capacity; //队列容量
int Front; //队首
int Rear; //队尾
ElementType *Array;
}*Queue;
Queue CreateQueue(int MaxElements);
bool IsEmpty(Queue Q);
bool IsFull(Queue Q);
int Length(Queue Q);
bool Enqueue(ElementType X, Queue Q);
ElementType Front(Queue Q);
bool FrontAndDequeue(Queue Q, ElementType &E);
int main()
{
Queue newQ = CreateQueue(5);
if(IsEmpty)
cout << "Is empty" << endl;
for(int i = 0; i < 5; i++)
if(!Enqueue(i, newQ))
cout << "IsFull" << endl;
for(int i = 0; i < 5; i++)
{
int num = 0;
FrontAndDequeue(newQ, num);
cout << num << endl;
}
cout << endl;
for(int i = 4; i < 9; i++)
Enqueue(i, newQ);
for(int i = 0; i < 5; i++)
{
int num = 0;
FrontAndDequeue(newQ, num);
cout << num << endl;
}
if(!IsFull(newQ))
cout << "IsFull" << endl;
system("pause");
return 0;
}
Queue CreateQueue(int MaxElements)
{
Queue Q = (Queue)malloc(sizeof(Queue));
Q->Capacity = MaxElements + 1; //这里留意一下,为什么要加1,如果不加1会咋样(关于判表空以及表满操作)
Q->Front = Q->Rear = 0;
Q->Array = new ElementType[MaxElements];
return Q;
}
bool IsEmpty(Queue Q)
{
if(Q->Front == Q->Rear)
return true;
return false;
}
bool IsFull(Queue Q)
{
if((Q->Rear + 1) % Q->Capacity == Q->Front)
return true;
return false;
}
int Length(Queue Q)
{
return (Q->Rear - Q->Front + Q->Capacity) % Q->Capacity;
}
bool Enqueue(ElementType X, Queue Q)
{
if(IsFull(Q))
return false;
Q->Array[Q->Rear] = X;
Q->Rear = (Q->Rear + 1) % Q->Capacity;
return true;
}
ElementType Front(Queue Q)
{
if(!IsEmpty(Q))
return Q->Array[Q->Front];
return -1;
}
/*
这里有个很有意思的事,这种队列的front直接指向队首,而rear指向队尾的后一格
故这里必须用引用来返回队首值,来完成取队首且出列操作
如果是front指向队首前一格,而rear直接指向队尾
那这里就可以直接使用return来完成操作
ElementType FrontAndDequeue(Queue Q)
{
if(IsEmpty(Q))
return NULL;
Q->Front = (Q->Front + 1) % Q->Capacity;
return Q->Array[Q->Front];
}
其他一些操作也同样需要修改,说实话我是建议这种
front指向队首前一格,而rear直接指向队尾
但我现在懒得改了,道理自己想想就很好修改了
*/
bool FrontAndDequeue(Queue Q, ElementType &E)
{
if(IsEmpty(Q))
return false;
E = Q->Array[Q->Front];
Q->Front = (Q->Front + 1) % Q->Capacity;
return true;
}
链表队列(Linked queue)
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef int ElementType;
//整体使用引用来进行修改操作
typedef struct Node
{
ElementType Data;
struct Node *next;
}*QueuePtr;
typedef struct LinkQueue
{
QueuePtr rear;
QueuePtr front;
}Queue;
void Initiate(Queue &Q);
bool IsEmpty(Queue Q);
void Enqueue(ElementType X, Queue &Q);
bool DequeueAndFront(Queue &Q, ElementType &e);
void DestoryQueue(Queue &Q);
int main()
{
Queue newQ;
Initiate(newQ);
if(IsEmpty(newQ))
cout << "Is empty" << endl;
for(int i = 4; i < 23; i++)
Enqueue(i, newQ);
for(int i = 0; i < 9; i++)
{
int num = 0;
DequeueAndFront(newQ, num);
cout << num << endl;
}
DestoryQueue(newQ);
system("pause");
return 0;
}
void Initiate(Queue &Q)
{
Q.front = Q.rear = (QueuePtr)malloc(sizeof(Node));
Q.front->next = NULL;
}
bool IsEmpty(Queue Q)
{
return Q.front->next == NULL;
}
void Enqueue(ElementType X, Queue &Q)
{
QueuePtr tmp = (QueuePtr)malloc(sizeof(Node));
tmp->Data = X;
tmp->next = NULL;
Q.rear->next = tmp;
Q.rear = tmp;
if(IsEmpty(Q))
Q.front->next = tmp;
}
bool DequeueAndFront(Queue &Q, ElementType &e)
{
if(IsEmpty(Q))
return false;
QueuePtr tmp = (QueuePtr)malloc(sizeof(Node));
tmp = Q.front->next;
e = Q.front->next->Data;
Q.front->next = tmp->next;
if(Q.rear == tmp)
Q.rear = Q.front;
free(tmp);
return true;
}
void DestoryQueue(Queue &Q)
{
while(Q.front)
{
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
}
C++STL < queue >
有兴趣就自己搜搜,反正很简单
用两个栈来实现一个队列
也没啥难度,自己想想,我懒得打了
可以参考:https://www.cnblogs.com/zhuli19901106/p/3788729.html