1、容器适配器
容器适配器是一种设计模式,这种模式是将一个类的接口转换成客户希望的另外一个接口
例如:
2、deque(双端队列)
deque是一种双开口的“连续”空间的数据结构,可以在头尾两端进行插入和删除操作,时间复杂度为O(1)
deque并不是真正的连续空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组
双端队列的实现:指针数组(每一个元素缓冲区的首地址)+缓冲区(每一个缓冲区都是定长的,大小相同)
deque的优点:增容代价小,头插头删效率高——O(1),支持随机访问(访问效率比vector略低),相对于list不容易产生内存碎片
缺陷:不适合遍历,中间位置插入和删除效率比较低
3、stack
stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,只能从容器的一端进行元素的插入与提取操作
stack的底层容器应该支持以下操作:empty(判空)、back(获取尾部元素)、push_back(尾插)、pop_back(尾删)
标准容器vector、deque、list均符合这些操作,默认使用deque
stack的操作:
- stack()——构造空栈;
- empty()——判空;
- size()——返回stack元素个数;
- top()——返回栈顶元素;
- push()——元素入栈
- pop()——出栈
接口测试:
stack的模拟实现:
template <class T, class container=deque<T>>
class Stack
{
public:
void push(const T& val)
{
_v.push_back(val);
}
void pop()
{
_v.pop_back();
}
T& top()
{
return _v.back();
}
bool empty()
{
return _v.empty();
}
size_t size()
{
return _v.size();
}
private:
container _v;
};
模拟实现接口测试:
4、queue
队列是一种容器适配器,专门用于先进先出的操作,从容器一端插入元素,另一端提取元素
queue的底层容器应该支持以下操作:empty(判空)、front(返回对头元素)、back(返回队尾元素)、push_back(尾插)、pop_front(头删)、size(返回元素个数)
标准容器deque、list均符合这些操作,默认使用deque
queue的操作:
- queue()——构造空队列;
- empty()——判空;
- size()——返回队列有效元素个数;
- front()——返回对头元素;
- back()——返回队尾元素
- push()——元素入队
- pop()——出队
接口测试:
queue的模拟实现:
template <class T, class container=deque<T>>
class Queue
{
public:
void push(const T& val)
{
_lst.push_back(val);
}
void pop()
{
_lst.pop_front();
}
T& front()
{
return _lst.front();
}
bool empty()
{
return _lst.empty();
}
T& back()
{
return _lst.back();
}
size_t size()
{
return _lst.size();
}
private:
container _lst;
};
模拟实现接口测试:
5、priority_queue
优先队列是一种容器适配器
priority_queue的底层容器应该支持以下操作:empty(判空)、front(返回第一个元素)、push_back(尾插)、pop_back(尾删)、size(返回元素个数)
标准容器deque、vector均符合这些操作,默认使用vector,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此,priority_queue就是堆
注意:默认情况下,priority_queue是大堆
优先级队列:
比较规则->仿函数类
仿函数类->必须重载 返回值 operator() (参数列表)
数据的比较:内置类型:本身支持大于小于比较;自定义类型:需重载<,>运算符
仿函数类:
使用方式类似于函数调用:
完整:仿函数对象.operator()(参数列表)
简写形式:仿函数对象(参数列表)
priority_queue的操作:
- priority_queue()/priority_queue(first, last)——构造空优先级队列;
- empty()——判空;
- top()——返回堆顶元素
- push()——元素入队
- pop()——出队
接口测试:
priority_queue模拟实现
//仿函数类
template <class T>
struct Less
{
bool operator()(const T& val1,const T& val2)
{
return val1 < val2;
}
};
template <class T>
struct Greater
{
bool operator()(const T& val1, const T& val2)
{
return val1 > val2;
}
};
template <class T, class Container = vector<T>, class Compare=Less<T>>
class PriorityQueue
{
public:
void shiftUp(int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (_com(_c[parent], _c[child]))
{
swap(_c[parent], _c[child]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
void push(const T& val)
{
_c.push_back(val);
shiftUp(_c.size() - 1);
}
void pop()
{
swap(_c[0], _c[_c.size() - 1]);
_c.pop_back();
shiftDown(_c[0]);
}
T& top()
{
return _c.front();
}
bool empty()
{
return _c.empty();
}
size_t size()
{
return _c.size();
}
void shiftDown(int parent)
{
int child = parent * 2 + 1;
while (child<_c.size())
{
if (child+1<_c.size() && _com( _c[child],_c[child+1]))
{
child += 1;
}
if (_com(_c[parent], _c[child]))
{
swap(_c[parent], _c[child]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
private:
Container _c;
Compare _com;
};