队列的概念:
只允许在一端进行插入,一端进行删除的特殊线性表。进行插入的称为队尾,删除一端的称为队头。队列具有先进先出的特性(FIFO)。
一、顺序队列:
1、队头不动,入队时,尾部后移一位,出队时,队头后的每一个元素向前搬移。
程序实现
#define size 10
template<class T>
class Queue
{
public:
Queue()
:array(new T[size])
, front(0)
, rear(0)
{}
//入队列
void push(const T& data)
{
if (rear==size)
cout << "队列已满!" << endl;
array[rear++] = data;
}
//出队列
void pop()
{
if (empty())
return;
//从前往后搬移元素
for (size_t i = 0; i < Size(); ++i)
{
array[i] = array[i + 1];
}
rear--;
}
//队列元素个数
size_t Size()
{
return rear;
}
T& first()
{
return array[front];
}
const T& first()const
{
return array[front];
}
T& Back()
{
return array[rear - 1];
}
const T& Back()const
{
return array[rear - 1];
}
bool empty()
{
if (front == rear)
{
return true;
}
return false;
}
private:
T* array;
size_t front;
size_t rear;
};
缺点:有大量的数据搬移。
2、出队列时,队头向后移动一个位置。
程序实现:
#define size 5
template<class T>
class Queue
{
public:
Queue()
:array(new T[size])
, front(0)
, rear(0)
{}
//入队列
void push(const T& data)
{
if (rear == size)
cout << "队列已满!" << endl;
array[rear++] = data;
}
//出队列
void pop()
{
front++;
}
//队列元素个数
size_t Size()
{
return rear-front;
}
T& first()
{
return array[front];
}
const T& first()const
{
return array[front];
}
T& Back()
{
return array[rear - 1];
}
const T& Back()const
{
return array[rear - 1];
}
bool empty()
{
if (front == rear)
{
return true;
}
return false;
}
private:
T* array;
size_t front;
size_t rear;
};
缺点:会出现“假溢出”的现象。
假溢出:顺序队列因多次入队列和出队操作,出现尚有存储空间但不能进行入队列的操作而引起的溢出。
真溢出:顺序队列最大存储空间已存满而要求进入队列的操作引起的溢出。
解决假溢出的方法就是让队列头尾相接,就出现了循环队列。
二、循环队列
循环队列实现起来,当front==rear时,究竟是队满和队空?
给出三个解决方法:
1.少用一个存储单元
#define capacity 8
template<class T>
class Queue
{
public:
Queue()
:array(new T[capacity])
, front(0)
, rear(0)
{}
//入队列
void push(const T& data)
{
if ((rear + 1) % capacity == front)
{
cout << "队列已满!" << endl;
}
else
{
array[rear++] = data;
rear = rear%capacity;
}
}
//出队列
void pop()
{
if (rear%capacity == front%capacity)
cout << "队列为空!" << endl;
else
{
front++;
}
}
//队列元素个数
const size_t Size()const
{
return (rear+capacity-front)%capacity;
}
T& first()
{
return array[front%capacity];
}
const T& first()const
{
return array[front%capacity];
}
T& Back()
{
return array[(rear + capacity- 2)%(capacity - 1)];
}
const T& Back()const
{
return array[(rear + capacity - 2) % (capacity - 1)];
}
bool empty()
{
if (front == rear)
{
return true;
}
return false;
}
private:
T* array;
size_t front;
size_t rear;
};
2.标记flag
#define capacity 5
template<class T>
class Queue
{
public:
Queue()
:array(new T(capacity))
,_front(0)
,_back(0)
{}
bool flag = false;
void push_back(const T& data)
{
//队满
if (_front == _back&&flag == true)
{
cout << "队列已满!" << endl;
return;
}
else
{
array[_back++] = data;
_back %= capacity;
flag = true;
}
}
void pop_front()
{
if (empty())
{
cout << "队列为空!" << endl;
return;
}
else
{
_front++;
_front %= capacity;
flag = false;
}
}
const size_t Size()const
{
if (_front == _back)
{
if (flag == true)
return capacity;
else
return 0;
}
return (_back + capacity - _front) % capacity;
}
T& first()
{
return array[_front];
}
const T& first()const
{
return array[_front];
}
T& back()
{
return array[_back - 1];
}
const T& back()const
{
return array[_back - 1];
}
bool empty()
{
if (_front == _back&&flag == false)
return true;
return false;
}
private:
T* array;
int _front;
int _back;
};
3.计数器count
#define N 5
template<class T>
class Queue
{
public:
Queue()
:_array(new T(N))
,_front(0)
, _rear(0)
, count(0)
{}
void push_back(const T& data)
{
if (count == N)//判满
{
cout << "队列已满!" << endl;
}
else
{
_array[_rear++] = data;//将元素入队
count++;
if (_rear == N)//走出来了
_rear = 0;//清零
else
_rear %= N;
}
}
void pop_front()
{
if (count == 0)
cout << "队列为空!" << endl;
else
{
_front++;
count--;
}
}
const size_t Size()const
{
return count;
}
T& first()
{
return _array[_front % N];
}
const T& first()const
{
return _array[_front % N];
}
T& back()
{
return _array[(_rear - 1 + N) % N];
}
const T& back()const
{
return _array[(_rear - 1 + N) % N];
}
bool empty()
{
return count == 0;
}
private:
T* _array;
int _front;
int _rear;
int count;
};