在STL的实现中,经常会复用已经完成实现的容器去实现另外一种容器(代码复用思想的具体体现),此时,前者(已经完成实现的容器)就称为后者(待实现的容器)的容器适配器,容器适配器的类型在代码设计中作为待实现容器的类模板参数.
比如,STL的stack和queue就是利用容器适配器思想来实现的
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;
};
deque是STL标准库中的双端队列,其存储结构是用指针数组管理的一系列数组集合,它同时支持时间复杂度为O(1)的数据头插头删,尾插尾删操作
C++中的仿函数实质上是将()运算符重载封装在类中,使被封装起来的函数其可以依托于类对象作为"函数形参"传入其他函数中进行调用,C++设计仿函数的目的是为了取代C语言中的函数指针,有效地提高了代码的封装性
template<class DataType>
class less
{
public:
bool operator()(const DataType& data1, const DataType& data2)
{
return data1 < data2;
}
};
template<class DataType>
class greater
{
public:
bool operator()(const DataType& data1, const DataType& data2)
{
return data1 > data2;
}
};
template<class DataType, class Container = std::vector<DataType>, class Compare = less<DataType>>
class priority_queue
{
public:
// 创造空的优先级队列
priority_queue() {};
//用迭代器区间建堆,采用元素向下调整法建堆
template<class Iterator>
priority_queue(Iterator first, Iterator last);
//堆插入接口
void push(const DataType& data);
//堆顶元素出队接口
void pop();
//返回队列元素个数的接口
size_t size()const;
//队列判空接口
bool empty()const;
// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性
const DataType& top()const;
private:
//元素向上调整接口
void AdjustUP(int child);
//元素向下调整接口
void AdjustDown(int parent);
}
private:
//储存堆的物理容器
Container _array;
};
//用仿函数来实现比较器,用于控制堆的类型
//用于建大堆的比较函数
template<class DataType>
class less
{
public:
bool operator()(const DataType& data1, const DataType& data2) const
{
return data1 < data2;
}
};
//用于建小堆的比较函数
template<class DataType>
class greater
{
public:
bool operator()(const DataType& data1, const DataType& data2) const
{
return data1 > data2;
}
};
less
来实例化priority_queue的Compare模板参数则建立大根堆greater
来实例化priority_queue的Compare模板参数则建立小根堆 //元素向上调整接口
void AdjustUP(int child)
{
//创建数据比较函数(仿函数类)
Compare comparator;
int parent = (child - 1) / 2;
while (child > 0)
{
if (comparator(_array[parent] , _array[child]))
{
std::swap(_array[child], _array[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//元素向下调整接口
void AdjustDown(int parent)
{
//创建数据比较函数(仿函数类)
Compare comparator;
//先取左孩子
int child = 2 * parent + 1;
while (child < size())
{
//取出左右孩子的较大值(或较小值)
if (child + 1 < size() && comparator(_array[child] , _array[child + 1]))
{
child++;
}
if (comparator(_array[parent] , _array[child]))
{
std::swap(_array[parent], _array[child]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
namespace Mypriority_queue
{
//用仿函数来实现比较器,用于控制堆的类型
//用于建大堆的比较函数
template<class DataType>
class less
{
public:
bool operator()(const DataType& data1, const DataType& data2) const
{
return data1 < data2;
}
};
//用于建小堆的比较函数
template<class DataType>
class greater
{
public:
bool operator()(const DataType& data1, const DataType& data2) const
{
return data1 > data2;
}
};
template<class DataType, class Container = std::vector<DataType>, class Compare = less<DataType>>
class priority_queue
{
public:
// 创造空的优先级队列
priority_queue() {};
//用迭代器区间建堆,采用元素向下调整法建堆
template<class Iterator>
priority_queue(Iterator first, Iterator last)
{
//将元素都尾插到数组中
for (auto it = first; it != last; ++it)
{
_array.push_back(*it);
}
//采用向下调整建堆,建堆时间复杂度为O(N);
for (int tail = (size() - 1 - 1) / 2; tail >= 0; --tail)
{
AdjustDown(tail);
}
}
//堆插入接口
void push(const DataType& data)
{
//先将元素尾插到容器中,再执行元素向上调整
_array.push_back(data);
AdjustUP(size() - 1);
}
//堆顶元素出队接口
void pop()
{
assert(!empty());
//先将堆顶元素交换到堆尾,然后将堆尾元素移除,最后将堆顶元素向下调整恢复堆的结构
std::swap(_array.front(), _array.back());
_array.pop_back();
AdjustDown(0);
}
//返回队列元素个数的接口
size_t size()const
{
return _array.size();
}
//队列判空接口
bool empty()const
{
return 0 == size();
}
// 堆顶元素不允许修改,因为:堆顶元素修改可以会破坏堆的特性
const DataType& top()const
{
assert(!empty());
return _array.front();
}
private:
//元素向上调整接口
void AdjustUP(int child)
{
Compare comparator;
int parent = (child - 1) / 2;
while (child > 0)
{
if (comparator(_array[parent] , _array[child]))
{
std::swap(_array[child], _array[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//元素向下调整接口
void AdjustDown(int parent)
{
Compare comparator;
//先取左孩子
int child = 2 * parent + 1;
while (child < size())
{
//取出左右孩子的较大值
if (child + 1 < size() && comparator(_array[child] , _array[child + 1]))
{
child++;
}
if (comparator(_array[parent] , _array[child]))
{
std::swap(_array[parent], _array[child]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
private:
//储存堆的物理容器
Container _array;
};
}