C++泛化双端队列
循环双端队列
双端队列可以在队首和队尾进行入队操作、出队操作的特殊队列。
循环双端队列是充分利用空间,使用格外的数据存储队头和队尾,这里利用数组进行实现。
循环双端队列(CircleQueue.h)
/*************************************************************************
> File Name : CircleDeque.h
> Author : Harold
> Mail : 2106562095@qq.com
> Github : www.github.com/Haroldcc
> Created Time : 2020年03月07日 13时21分25秒
************************************************************************/
#ifndef CIRCLEQUEUE_H_
#define CIRCLEDEQUE_H_
#include <iostream>
#include <sstream>
#include "./myExceptions.h"
/***** 循环双端队列 *****/
/* 利用数组进行实现
* 双端队列:表示头部和尾部都可以进行出入队操作
*/
template <typename T>
class CircleDeque
{
private:
int front; // 队头
int size; // 队内元素个数
T *elements; // 实现队列的数组
int m_capacity; // 数组容量
// 验证数组的容量,是否需要进行数组扩容
void ensureCapacity(int capacity);
// 传入队列中的索引,映射到数组上获取数组上的索引
int index(int index);
public:
// 构造函数
CircleDeque(int initialCapacity = 10);
// 析构函数
~CircleDeque() { delete[] this->elements; }
int Size() const { return this->size; }
bool isEmpty() const { return this->size == 0; }
// 队尾入队
void enQueueRear(const T &element);
// 队头出队
T deQueueFront();
// 队头入队
void enQueueFront(const T &element);
// 队尾出队
T deQueueRear();
// 获取队头
T &head() const;
// 获取队尾
T &tail() const;
// 清空队列
void clear();
// 输出结果
void output(std::ostream &out) const;
};
// 验证数组的容量,是否需要进行数组扩容
template <typename T>
void CircleDeque<T>::ensureCapacity(int capacity)
{
int oldCapacity = this->m_capacity;
if (oldCapacity >= capacity)
{
return;
}
int newCapacity = oldCapacity + (oldCapacity >> 1);
T *newElements = new T[newCapacity];
for (int i = 0; i < this->size; i++)
{
newElements[i] = elements[index(i)];
}
delete[] this->elements;
this->elements = newElements;
this->front = 0;
this->m_capacity = newCapacity;
}
// 传入队列中的索引,映射到数组上获取数组上的索引
template <typename T>
int CircleDeque<T>::index(int index)
{
index += this->front;
if (index < 0)
{
return index + this->m_capacity;
}
return index % this->m_capacity;
}
// 构造函数
template <typename T>
CircleDeque<T>::CircleDeque(int initialCapacity)
{
if (initialCapacity < 1)
{
std::ostringstream s;
s << "初始化容量 = " << initialCapacity << "必须 > 0";
throw illegalParameterValue(s.str());
}
this->front = 0;
this->size = 0;
this->elements = new T[initialCapacity];
this->m_capacity = initialCapacity;
}
// 队尾入队
template <typename T>
void CircleDeque<T>::enQueueRear(const T &element)
{
ensureCapacity(this->size + 1);
this->elements[index(this->size)] = element;
this->size++;
}
// 队头出队
template <typename T>
T CircleDeque<T>::deQueueFront()
{
T frontElement = this->elements[this->front];
this->elements[this->front] = 0;
this->front = index(1);
this->size--;
return frontElement;
}
// 队头入队
template <typename T>
void CircleDeque<T>::enQueueFront(const T &element)
{
ensureCapacity(this->size + 1);
this->front = index(-1);
this->elements[this->front] = element;
this->size++;
}
// 队尾出队
template <typename T>
T CircleDeque<T>::deQueueRear()
{
int rearIndex = index(this->size - 1);
T rear = this->elements[rearIndex];
this->elements[rearIndex] = 0;
this->size--;
return rear;
}
// 获取队头
template <typename T>
T &CircleDeque<T>::head() const
{
return this->elements[this->front];
}
// 获取队尾
template <typename T>
T &CircleDeque<T>::tail() const
{
return this->elements[index(this->size - 1)];
}
// 清空队列
template <typename T>
void CircleDeque<T>::clear()
{
for (int i = 0; i < this->size; i++)
this->elements[index(i)] = 0;
this->size = this->front = 0;
}
// 输出结果
template <typename T>
void CircleDeque<T>::output(std::ostream &out) const
{
out << "capacity = " << this->m_capacity << " size = " << this->size
<< " front = " << this->front << ", [";
for (int i = 0; i < this->m_capacity; i++)
{
if (i != 0)
out << ", ";
out << this->elements[i];
}
out << "]";
}
template <typename T>
std::ostream &operator<<(std::ostream &out, const CircleDeque<T> &queue)
{
queue.output(out);
return out;
}
#endif
测试(testCircleQueue.cpp)
/*************************************************************************
> File Name : testCircleDeque.cpp
> Author : Harold
> Mail : 2106562095@qq.com
> Github : www.github.com/Haroldcc
> Created Time : 2020年03月07日 15时49分27秒
************************************************************************/
#include "CircleDeque.h"
#include <iostream>
using namespace std;
int main()
{
CircleDeque<int> qu;
// 8 7 6 5 4 3 2 1 101 102 103 104 105 106 107 108 109尾
for (int i = 0; i < 10; i++)
{
qu.enQueueFront(i + 1);
qu.enQueueRear(i + 100);
}
cout << qu << endl;
for (int i = 0; i < 3; i++)
{
qu.deQueueFront();
qu.deQueueRear();
}
qu.enQueueFront(11);
qu.enQueueFront(12);
cout << qu << endl;
while (!qu.isEmpty())
{
cout << qu.deQueueFront() << endl;
}
return 0;
}
输出
capacity = 22 size = 20 front = 20, [8, 7, 6, 5,
4, 3, 2, 1, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, -1163005939, -1163005939, 10, 9]
capacity = 22 size = 16 front = 21, [11, 7, 6, 5, 4, 3, 2, 1, 100, 101, 102, 103, 104, 105, 106, 0, 0, 0, -1163005939, -1163005939, 0, 12]
12
11
7
6
5
4
3
2
1
100
101
102
103
104
105
106
C++泛化双端队列的更多相关文章
- lintcode二叉树的锯齿形层次遍历 (双端队列)
题目链接: http://www.lintcode.com/zh-cn/problem/binary-tree-zigzag-level-order-traversal/ 二叉树的锯齿形层次遍历 给出 ...
- lintcode 滑动窗口的最大值(双端队列)
题目链接:http://www.lintcode.com/zh-cn/problem/sliding-window-maximum/# 滑动窗口的最大值 给出一个可能包含重复的整数数组,和一个大小为 ...
- STL---deque(双端队列)
Deque是一种优化了的.对序列两端元素进行添加和删除操作的基本序列容器.它允许较为快速地随机访问,但它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结 ...
- hdu-5929 Basic Data Structure(双端队列+模拟)
题目链接: Basic Data Structure Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 65536/65536 K (Ja ...
- HDU 4286 Data Handler --双端队列
题意:有一串数字,两个指针,然后一些添加,删除,反转,以及移动操作,最后输出序列. 解法:可以splay做,但是其实双端队列更简便. 维护三个双端队列LE,MI,RI分别表示[L,R]序列左边,[L, ...
- 双端队列(单调队列)poj2823 区间最小值(RMQ也可以)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 41844 Accepted: 12384 ...
- Java 集合深入理解(10):Deque 双端队列
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 什么是 Deque Deque 是 Double ended queue (双端队列) 的缩写,读音和 deck 一样,蛋 ...
- BZOJ2457 BeiJing2011 双端队列
[问题描述] Sherry现在碰到了一个棘手的问题,有N个整数需要排序. Sherry手头能用的工具就是若干个双端队列. 她需要依次处理这N个数,对于每个数,Sherry能做以下两件事 ...
- Fork/Join框架之双端队列
简介 ForkJoinPool管理着ForkJoinWorkerThread线程,ForkJoinWorkerThread线程内部有一个双端队列,这个双端队列主要由一个数组queue.数组下标queu ...
随机推荐
- linux系统权限(基本权限)
linux的系统权限:r-- 100 4-w- 010 2--x 001 1 [root@localhost ~]# ll -d dir drwxrwxrwx root root Nov : di ...
- Laravel5.4 队列简单配置与使用
概述 什么是队列? 百度百科是这样说的 “队列”是在传输过程中保存数据的容器. 举几个生活中例子: * iphone手机新款发布,三里屯iphone进的新货.大家要排队买,不能说一大堆人一起冲进去,那 ...
- 学习python-20191230(1)-Python Flask高级编程开发鱼书_第04章_应用、蓝图与视图函数
视频06: 1.自动导包快捷键——默认为alt + enter 键组合 选中的字符由小写变为大写——Ctrl + Shift + U键组合 2.DataRequired()——防止用 ...
- java实现银行管理系统
Bank类 package First; import java.util.TreeSet; //银行类public class Bank { private String Bankna ...
- 面试你能搞懂JVM了吗,快看看这20道JVM面试题
1.内存模型以及分区,需要详细到每个区放什么?2.堆里面的分区:Eden,survival (from+ to),老年代,各自的特点?3.对象创建方法,对象的内存分配,对象的访问定位?4.GC 的两种 ...
- motionbuilder卸载/完美解决安装失败/如何彻底卸载清除干净motionbuilder各种残留注册表和文件的方法
在卸载motionbuilder重装motionbuilder时发现安装失败,提示是已安装motionbuilder或安装失败.这是因为上一次卸载motionbuilder没有清理干净,系统会误认为已 ...
- 3DSMAX卸载/完美解决安装失败/如何彻底卸载清除干净3DSMAX各种残留注册表和文件的方法
在卸载3dsmax重装3dsmax时发现安装失败,提示是已安装3dsmax或安装失败.这是因为上一次卸载3dsmax没有清理干净,系统会误认为已经安装3dsmax了.有的同学是新装的系统也会出现3ds ...
- 记一笔MyBatis的坑
记一笔MyBatis的坑 1.sql查询concat()连接函数xml运行查询乱码 ) , ), char)'%') bll FROM fact_dkxx sq 由于连接的字符串中包含数字与百分比字符 ...
- mongoDB连接信息及生成对应的collection生成代码
.net,个人封装MONGODDB的操作. using System; using System.Collections.Generic; using System.Linq; using Syste ...
- nginx在反向代理侧实现ssl
被代理的webserver为lnmp项目,现在需要在反向代理侧使用nginx实现ssl的反向代理(域名解析在反代的ip上),配置如下: upstream XXX { server 192.168.0. ...