队列介绍
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作 的特殊线性表。 进行插入操作的一端称为队尾,通常称为入队列;进行删除操作的一端称为队头,通常称为出队列。 队列具有先进先出的特性(FIFO)。
顺序队列
【实现方式一】 队头不动,出栈时队头后的所有元素向前移动
【实现方式二】 出队列时,队头向后移动一个位置
如果再有F、G进行入队操作,就会出现假溢出问题
顺序队列因多次入队列和出队列操作后出现的尚有存储空间但不能再进行入队列操作的溢出称作为假 溢出。 顺序队列最大存储空间已经存满而又要求进行入队列操作所引起的溢出称为真溢出。
为充分利用向量空间,克服”假溢出”现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。
【队列满和队列空判断】
1 少用一个存储单元
如果少用一个存储空间,则也队尾指针加1等于对头指针为队列满的判断条件: (rear+1)%MaxSize==front 队列空的条件仍旧为rear == front
2 设置一个标记位
设置标记为flag,初始时置flag = 0;每当入队列操作成功,就置flag=1;每当出队列成功就置 flag=0.此时判断队列空 的条件为:rear == front && flag == 0;判断队列满的条件为rear == front&& flag == 1
3 设置一个计数器
设置计数器count,初始时置count=0,每当入队列操作成功,就是count加1,每当出队列成 功,就使count减1。此时队列空的判断条件为:count==0;队列满的判断条件为count>0 && rear == front 或者count == MaxSize
下面是循环队列实现的源代码:
#include <iostream>
using namespace std;
循环队列
template<class T>
class Queue
{
public:
Queue(size_t capacity = 10)
{
_pData = new T[capacity];
_front = 0;
_rear = 0;
_count = 0;
_capacity = capacity;
}
void Push(const T& data)
{
//先对队列进行判满,如果队列为满,不可进行插入
if(_count == _capacity)
{
return;
}
else
{
_pData[_rear++] = data;
_count++;
_rear %= _capacity;
}
}
void Pop()
{
if(!Empty())
{
_front++;
_front %= _capacity;
_count--;
}
}
bool Empty()const
{
return 0 == _count;
}
size_t Size()const
{
return _count;
}
T& Front()
{
return _pData[_front];
}
T& Front()const
{
return _pData[_front];
}
T& Rear()
{
return _pData[_rear];
}
T& Rear()const
{
return _pData[_rear];
}
protected:
T* _pData;
size_t _front; //存放头指针位置
size_t _rear; //存放尾指针位置
size_t _capacity; //循环队列的空间
size_t _count; //已经存放到队列的元素个数,方便判断队列空和队列满
//队列空的判断条件:count = 0
//队列满的判断条件:count = capacity
};
int main()
{
Queue<int> q1(5);
q1.Push(1);
q1.Push(2);
q1.Push(3);
q1.Push(4);
q1.Pop();
q1.Pop();
q1.Push(5);
q1.Push(6);
q1.Push(7);
system("pause");
return 0;
}