【c++】模拟实现循环队列 三种方法(标识、浪费一个空间、计数器)

来源:互联网 发布:java urlencoder js 编辑:程序博客网 时间:2024/06/05 21:59

什么是循环队列?

为充分利用向量空间,克服”假溢出“现象的方法:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。

假象成如图:


但实际上存储空间还是一段连续的空间。

空队列:


当有元素入队时:


元素出队:


元素继续入队时:


在这里吃瓜群众们可能有个疑问,队尾标记rear 是怎么就突然蹦到front的前面的?

观察我们可以发现当E入队时,rear = 5,

下一个将要入队的是F,那么按照假象的循环队列的话 rear应该变为0 ,也就是(rear+1)%容量,可以多计算几个值尝试,画图尝试一下,容易理解。

然后G入队时 rear+1 即可 。用一个对容量求余的方法,解决了 rear每次 向后推进的 改变。当然也可以判断入队时rear 是否等于容量 ,

当等于容量时,可以直接将rear置为0。

然后继续入队:


看到这里可能吃瓜群众又有问题了,队列空的时候是rear = front  ,现在满的时候也是 rear = front,这怎么判断呢? 下面来介绍一下解决这个问题的三种方法。

①、增加一个标识flag ,初始的时置为false,每当有元素入队时让flag = true,每当有元素出队时,让flag = false,在触发rear = front 的上一个操作决定了是空还是满。

这样在判断空的时候 ,要判断 front == rear 和 flag 为假要同时成立,即( front == rear ) && !front 整体为真时,队列空。

( front == rear ) && front 时 队列满。


代码:

#include <cassert>#include <iostream>using namespace std;// 循环队列 flag 方法template<typename T>class Queue{public:// 构造函数Queue(const size_t capacity = 10):_front(0),_rear(0),_capacity(capacity),IsFull(false){_capacity = _capacity >= 10 ? _capacity:10;_array = new T[_capacity];}// 拷贝构造函数Queue(const Queue<T>& que):_front(que._front),_rear(que._rear),_capacity(que._capacity),IsFull(que.IsFull){_array = new T[que._capacity];if (Empty()) // (一) 空 不拷{return;}if(Full())   // (二) 满 都拷{for (size_t idx = 0; idx < _capacity; ++idx){_array[idx] = que._array[idx];}return;}// (三 )不满 2 种情况if(_front < _rear) //  1.队头 小于 队尾{for (size_t idx = _front; idx < _rear; ++idx){_array[idx] = que._array[idx];}}if (_front > _rear) // 2. 队头 大于 队尾{// 先拷贝0-rear 部分for (size_t idx = 0; idx < _rear; ++idx) {_array[idx] = que._array[idx];}// 再拷贝 _front- _capacity 部分for (size_t idx = _front; idx < _capacity; ++idx){_array[idx] = que._array[idx];}}}// 赋值运算符重载Queue<T>& operator=(const Queue<T>& que){if (this != &que){Queue<T> temp_que(que);std::swap(_array, temp_que._array);_front = que._front;_rear = que._rear;_capacity = que._capacity;IsFull = que.IsFull;}return *this;}// 元素个数size_t Length()const{// 满的时候 rear 和 front 重合 特殊处理一下if (Full()){return _capacity;}// 1. rear < front 左 + 右  0-rear  front -capacity // 2. rear > front rear-frontreturn (_rear + _capacity - _front)%_capacity;}// 队首T& Front(){assert(!Empty());return _array[_front];}const T& Front()const{assert(!Empty());return _array[_front];}// 队尾T& Back(){assert(!Empty());return _array[(_rear-1 + _capacity)%_capacity];}const T& Back()const{assert(!Empty());return _array[(_rear-1 + _capacity)%_capacity];}// 入队void Push(const T& data){assert(!Full());IsFull = true;_array[_rear] = data;_rear = (_rear+1)%_capacity;}// 出队void Pop(){assert(!Empty());IsFull = false;_front = (_front+1)%_capacity;}// 判满bool Full()const{if ( (_front==_rear) && IsFull ){return true;}else{return false;}}// 判空bool Empty()const{if ( (_front==_rear) && (!IsFull) ){return true;}else{return false;}}// 析构函数~Queue(){if (_array != NULL){delete[] _array;_array = NULL;_front = 0;_rear = 0;_capacity = 0;}}private:T* _array;size_t _front; // 栈首size_t _rear; // 栈尾size_t _capacity; // 容量bool IsFull; // 标记 用来判断栈满};int main(){// Queue<int> q1;// cout << q1.Length() << endl;// cout << q1.Empty() << endl;// cout << q1.Full() << endl;// q1.Push(1);// q1.Push(2);// q1.Push(2);// q1.Push(2);// q1.Push(2);// q1.Push(2);// q1.Push(2);// q1.Push(2);// q1.Push(2);// q1.Push(3);// cout << q1.Front() << endl;// cout << q1.Back() << endl;// cout << q1.Length() << endl;// cout << q1.Empty() << endl;// cout << q1.Full() << endl;Queue<int> q2;cout << q2.Length() << endl;cout << q2.Empty() << endl;cout << q2.Full() << endl;q2.Push(1);q2.Push(2);q2.Push(3);q2.Push(4);cout << q2.Front() << endl;cout << q2.Back() << endl;cout << q2.Length() << endl;cout << q2.Empty() << endl;cout << q2.Full() << endl;Queue<int> q3;q3 = q2;q3.Pop();q3.Pop();q3.Pop();q3.Pop();cout << q3.Length() << endl;cout << q3.Empty() << endl;cout << q3.Full() << endl;return 0;}

要注意在拷贝构造函数中分为三种情况去拷贝




②、浪费一个空间,当  front = rear 时为空, front = (rear + 1)%容量 未为满。


代码:

#include <cassert>#include <iostream>using namespace std;// 循环队列  浪费一个空间template<typename T>class Queue{public:// 构造函数Queue(const size_t capacity = 10):_front(0),_rear(0),_capacity(capacity){_capacity = _capacity >= 10 ? _capacity:10;_array = new T[_capacity];}// 拷贝构造函数Queue(const Queue<T>& que):_front(que._front),_rear(que._rear),_capacity(que._capacity){_array = new T[que._capacity];if (Empty()) // (一) 空 不拷{return;}if(Full())   // (二) 满 都拷{for (size_t idx = 0; idx < _capacity; ++idx){_array[idx] = que._array[idx];}return;}// (三 )不满 2 种情况if(_front < _rear) //  1.队头 小于 队尾{for (size_t idx = _front; idx < _rear; ++idx){_array[idx] = que._array[idx];}}if (_front > _rear) // 2. 队头 大于 队尾{// 先拷贝0-rear 部分for (size_t idx = 0; idx < _rear; ++idx) {_array[idx] = que._array[idx];}// 再拷贝 _front- _capacity 部分for (size_t idx = _front; idx < _capacity; ++idx){_array[idx] = que._array[idx];}}}// 赋值运算符重载Queue<T>& operator=(const Queue<T>& que){if (this != &que){Queue<T> temp_que(que);std::swap(_array, temp_que._array);_front = que._front;_rear = que._rear;_capacity = que._capacity;}return *this;}// 元素个数size_t Length()const{return (_rear + _capacity  - _front)%_capacity;}// 队首T& Front(){assert(!Empty());return _array[_front];}const T& Front()const{assert(!Empty());return _array[_front];}// 队尾T& Back(){assert(!Empty());return _array[(_rear-1 + _capacity)%_capacity];}const T& Back()const{assert(!Empty());return _array[(_rear-1 + _capacity)%_capacity];}// 入队void Push(const T& data){assert(!Full());_array[_rear] = data;_rear = (_rear+1)%_capacity;}// 出队void Pop(){assert(!Empty());_front = (_front+1)%_capacity;}// 判满bool Full()const{if ((_rear+1)%_capacity == _front){return true;}else{return false;}}// 判空bool Empty()const{if ( _front == _rear ){return true;}else{return false;}}// 析构函数~Queue(){if (_array != NULL){delete[] _array;_array = NULL;_front = 0;_rear = 0;_capacity = 0;}}private:T* _array;size_t _front; // 栈首size_t _rear; // 栈尾size_t _capacity; // 容量};



③、设置一个计数器Count ,当count = 0时,为空,count 等于容量时,队列满。代码与上面的方法差别不大,部分地方有修改。

#include <cassert>#include <iostream>using namespace std;// 循环队列 Count 计数template<typename T>class Queue{public:// 构造函数Queue(const size_t capacity = 10):_front(0),_rear(0),_capacity(capacity),_count(0){_capacity = _capacity >= 10 ? _capacity:10;_array = new T[_capacity];}// 拷贝构造函数Queue(const Queue<T>& que):_front(que._front),_rear(que._rear),_capacity(que._capacity),_count(que._count){_array = new T[que._capacity];if (Empty()) // (一) 空 不拷{return;}if(Full())   // (二) 满 都拷{for (size_t idx = 0; idx < _capacity; ++idx){_array[idx] = que._array[idx];}return;}// (三 )不满 2 种情况if(_front < _rear) //  1.队头 小于 队尾{for (size_t idx = _front; idx < _rear; ++idx){_array[idx] = que._array[idx];}}if (_front > _rear) // 2. 队头 大于 队尾{// 先拷贝0-rear 部分for (size_t idx = 0; idx < _rear; ++idx) {_array[idx] = que._array[idx];}// 再拷贝 _front- _capacity 部分for (size_t idx = _front; idx < _capacity; ++idx){_array[idx] = que._array[idx];}}}// 赋值运算符重载Queue<T>& operator=(const Queue<T>& que){if (this != &que){Queue<T> temp_que(que);std::swap(_array, temp_que._array);_front = que._front;_rear = que._rear;_capacity = que._capacity;_count = que._count;}return *this;}// 元素个数size_t Length()const{return _count;}// 队首T& Front(){assert(!Empty());return _array[_front];}const T& Front()const{assert(!Empty());return _array[_front];}// 队尾T& Back(){assert(!Empty());return _array[(_rear-1 + _capacity)%_capacity];}const T& Back()const{assert(!Empty());return _array[(_rear-1 + _capacity)%_capacity];}// 入队void Push(const T& data){assert(!Full());_count++;_array[_rear] = data;_rear = (_rear+1)%_capacity;}// 出队void Pop(){assert(!Empty());_count--;_front = (_front+1)%_capacity;}// 判满bool Full()const{if (_count == _capacity ){return true;}else{return false;}}// 判空bool Empty()const{if ( 0 == _count ){return true;}else{return false;}}// 析构函数~Queue(){if (_array != NULL){delete[] _array;_array = NULL;_front = 0;_rear = 0;_capacity = 0;_count = 0;}}private:T* _array;size_t _front; // 栈首size_t _rear; // 栈尾size_t _capacity; // 容量size_t _count; // 计数器};


0 0
原创粉丝点击