【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; // 计数器};
- 【c++】模拟实现循环队列 三种方法(标识、浪费一个空间、计数器)
- 数据结构(C实现)------- 顺序队列(循环队列之计数器实现)
- 模拟实现循环队列
- 循环队列及C语言实现<三>
- 【c++】模拟实现顺序队列方法一
- 【c++】模拟实现顺序队列方法二
- 实验三 模拟饭堂排队打饭管理软件(循环队列实现)
- 数据结构(C实现)------- 顺序队列(循环队列之少用一个存储空间实现) .
- Java实现三种(顺序,链式,循环)队列
- 循环队列实现(C++)
- C 循环队列实现
- 循环队列 c 实现!!!!
- 【C++】实现循环队列
- 【C++】模拟实现队列
- 循环队列的判断满、空的三种方法以及具体代码实现(数组实现)
- 实验三循环队列(c++)
- (002)循环队列的两种C/C++实现
- 数据结构(C语言)实现循环队列
- PHP线程安全版和非线程安全版
- JDBC 简介
- oracle 11g ORA-02291: 违反完整约束条件 - 未找到父项关键字
- 2016技术流水账
- 2016 年热门 Web 开发工具
- 【c++】模拟实现循环队列 三种方法(标识、浪费一个空间、计数器)
- C++链接属性
- android4.2关于BroadcastReceiver获取短信广播事件问题
- (13)裁剪之多边形裁剪
- 学习英语要善于持久战
- android怎样在同一行等间距地放置2到4个ImageView
- python中去掉空格项目
- C语言实验题――大小写转换
- 从Log4j迁移到LogBack的理由