1.仿函数
1.仿函数的作用
1.仿函数是一种重载了函数调用运算符的类对象,他的使用方法看起来与函数极其相似,却又有不同,因此成为仿函数
2.仿函数的定义与使用
我们现在写一个比较两个变量大小的仿函数以及函数
template<class T>
class Less
{
bool operator()(const T&a,const T&b )
{
return a < b;
}
};
template<class T>
bool Less(const T& a, const T& b )
{
return a < b;
}
仿函数的优势:复杂的函数指针很难看懂,而仿函数可以不用函数指针,直接传类,会简化操作
2.priority_queue
1.priority_queue的介绍
1.优先队列是一种容器适配器,STL中默认使用的容器是vector(deque也可以)
2.它存储数据的结构是堆默认是大堆
3.底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类,容器应该可以通过随机访问迭代器访问,并支持以下操作:empty(判空操作),back(获取尾部元素操作),push_back(尾插操作),pop_back(尾删操作)
4. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、 push_heap 和 pop_heap 来自动完成此操作。
2.成员变量
template<class T, class Container = vector<T>, class Compare = Less<T>>
class priority_queue
{
public:
//函数
private:
Container _con;
};
此处为直接模拟STL的格式,但事实上,在模板参数那里,应该把Container放到最后才合适,因为我们一般不会修改使用的容器,但会选择建一个大堆或小堆,STL的格式导致我们在调整为小堆时,必须也写容器才行
3.empty
bool empty()
{
reutrn _con.empty();
}
4.size(返回容器适配器的元素个数)
size_t size()
{
return _con.size();
}
5.top(返回堆顶元素)
constT& top()const
{
_con.front();
}
必须返回const因为如果一旦使数据改变则堆将不是大堆或小堆
6.入堆(尾插和向上调整)
void push(T& val)
{
_con.push_back(val);
UpAdjust();
}
void UpAdjust(size_t number)//大堆
{
int child = number - 1;
int parent = child = (child-1) / 2;
while (child)
{
if (_con[child] > _con[parent])
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child-1) / 2;
}
else
break;
}
}
此处可以使用模板,因为大堆和小堆只有大于号和小于号的区别
template<class T>
class Less
{
bool operator()(const T&a,const T&b )
{
return a < b;
}
};
template<class T>
class Greater
{
bool operator()(const T& a, const T& b)
{
return a > b;
}
};
void push(T& val)
{
_con.push_back(val);
UpAdjust();
}
Compare com;
void UpAdjust(size_t number)//大堆
{
int child = number - 1;
int parent = child = (child-1) / 2;
while (child)
{
if (com(_con[parent] , _con[child]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child-1) / 2;
}
else
break;
}
}
7.出堆(堆操作老套路,交换删除,堆顶向下调整,模板)
template<class T>
class Less
{
bool operator()(const T&a,const T&b )
{
return a < b;
}
};
template<class T>
class Greater
{
bool operator()(const T& a, const T& b)
{
return a > b;
}
};
Compare com;
void DownAdjust(size_t size)
{
int parent = 0;
int child = parent * 2+1;
while (child<size)
{
if (child<size&&com(_con[child], _con[child + 1]))
child++;
if (com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void pop()
{
swap(_con[0], _con[size() - 1]);
_con.pop_back();
DownAdjust(size());
}
3.反向迭代器
1.反向迭代器是一种适配器,它是根据不同容器的正向迭代器,来生成对应的反向迭代器
2.反向迭代器的rbegin对应迭代器的end位置,rend对应begin位置。
1.成员变量
template <class Iterator,class Ref,class Ptr>
struct ReverseItreator
{
typedef ReverseIterator<Iterator, Ref, Ptr> self;
Iterator it;
};
使用struct标明公有属性的同时,将一个正向迭代器作为成员变量
2.默认成员函数(只写缺省构造,其余编译器自动生成)
ReverseItreator(Iterator val=Iterator())
:it(val)
{}
3.operator*
Ref operator*()
{
Iterator its = it;
its--;
return *its;
}
4.operator--(提醒一下这是反向迭代器哦)
self operator--()
{
return ++it;
}
self operator--()const
{
Iterator its = it;
++it;
return its;
}
5.operator++
self operator++()
{
return --it;
}
self operator++()const
{
Iterator its = it;
--it;
return its;
}
6.operator->
Ptr operator->()
{
return & (*it);
}
7.operator!=,==
bool operator==(const self&s)
{
return it = s.it;
}
bool operator !=(const self& s)
{
return it = s.it;
}
4.反向迭代器应用(vector为例)
template<class T>
class vector
{
public:
typedef T* Iterator;
typedef const T* Const_Iterator;
typedef ReverseIterator<Iteartor, T&, T*> Reverse_Iterator;
typedef ReverseIterator<Iteartor, constT&,cosnt T*> Const_Reverse_Iterator;
Iterator end()
{
return _finish;
}
Const_Iterator end()const
{
return _finish;
}
Iterator begin()
{
return _start;
}
Const_Iterator begin()const
{
return _start;
}
private:
T* _start;
T* _finish;
};
5.反向迭代器函数(使用时调用正向迭代器的函数,因为不同容器的函数各不相同)
Reverse_Iterator rbegin()
{
return (Reverse_Iterator)end();
}
Const_Reverse_Iterator rbegin()const
{
return (Const_Reverse_Iterator)end();
}
Reverse_Iterator rend()
{
return (Reverse_Iterator)begin();
}
Const_Reverse_Iterator rend()const
{
return (Const_Reverse_Iterator)begin();
}