目录
1.容器适配器
适配器是一种设计模式,该模式是将一个类的接口转换成客户希望的另外一个接口。在数据结构实现时,可以采用不同的容器来适配同一数据结构,比如堆,栈,队列的实现。
例如:stack和queue的模拟实现
#pragma once
#include<deque>
using std::deque;
template<class T,class Container= deque<T>>
class stack
{
public:
stack() {}
void push(const T& x) { _c.push_back(x); }
void pop() { _c.pop_back(); }
T& top() { return _c.back(); }
const T& top()const { return _c.back(); }
size_t size()const { return _c.size(); }
bool empty()const { return _c.empty(); }
private:
Container _c;
};
template<class T, class Container = deque<T>>
class queue
{
public:
queue() {}
void push(const T& x) { _c.push_back(x); }
void pop() { _c.pop_front(); }
T& back() { return _c.back(); }
const T& back()const { return _c.back(); }
T& front() { return _c.front(); }
const T& front()const { return _c.front(); }
size_t size()const { return _c.size(); }
bool empty()const { return _c.empty(); }
private:
Container _c;
};
stack和queue使用deque作为默认的适配容器,原因是deque是一个双端队列的结构,它的头尾的插入和删除的效率很高,恰好适合这两个不需要在中间插入删除的数据结构,但是deque的底层结构也有缺陷,deque的底层结构可以看做是是分段连续的数组,故在遍历时需要检测每个数组的边界,故deque的随机访问效率是不如vector的,故deque的用途不广。
2.priority_queue的模拟实现
优先队列是用数组模拟实现的,故默认用支持快速随机访问的容器vector为佳。还需要一个用于比较元素大小的仿函数,库中的默认仿函数为less<T>,默认建的是大堆。仿函数其实是一个类模板,类重载了()这个运算符,故可以像看起来函数一样去调用operator()实现元素的大小比较。
模拟实现:
#include<vector>
using std::vector;
using std::swap;
//less<T> 建的是大堆
template<class T>
struct less
{
bool operator()(const T& e1, const T& e2)
{
return e1 < e2;
}
};
template<class T>
struct greater
{
bool operator()(const T& e1, const T& e2)
{
return e1 > e2;
}
};
template<class T, class Container = std::vector<T>, class Compare = less<T>>
class priority_queue
{
public:
priority_queue() = default;
template<class Iterator>
priority_queue(Iterator first, Iterator last)
:_c(first,last)
{
int parent = (_c.size() - 2) >> 1;
while (parent >= 0)
AdjustDown(parent--);
}
void push(const T& data)
{
_c.push_back(data);
AdjustUp(_c.size() - 1);
}
void pop()
{
std::swap(_c.front(), _c.back());
_c.pop_back();
AdjustDown(0);
}
size_t size()const { return _c.size(); }
const T& top()const { return _c.front(); }
bool empty()const { return _c.empty(); }
private:
void AdjustDown(int parent)
{
int child = parent * 2 + 1;
while (child < _c.size())
{
if (child + 1 < _c.size()
&& Compare()(_c[child], _c[child + 1]))
++child;
if (Compare()(_c[parent], _c[child]))
{
swap(_c[parent], _c[child]);
parent = child;
child = parent * 2 + 1;
}
else
return ;
}
}
void AdjustUp(int child)
{
int parent = (child - 1) >> 1;
while (child)
{
if (Compare()(_c[parent], _c[child]))
{
swap(_c[parent], _c[child]);
child = parent;
parent = (child - 1) >> 1;
}
else
return;
}
}
private:
Container _c;
};
简易测试:
int main()
{
priority_queue<int>pq;
pq.push(5243);
pq.push(23);
pq.push(312);
pq.push(35);
pq.push(567);
pq.push(878);
pq.push(9994);
while (!pq.empty())
{
cout << pq.top() << endl;
pq.pop();
}
return 0;
}