1.优先级队列
我们来看优先级队列的在STL中的内容
其实优先级队列的底层就是使用vector实现堆的控制排序,默认是大根的排序,这个排序的方式是通过仿函数实现的,所以我们先来看一道题理解,优先级队列。力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
这道题就可以使用优先级队列来解决,
我们用优先级队列的堆排序,使最大的数在堆顶,然后pop掉k-1次就是第k个大的数,这样堆顶就是我们想要的数。
2.优先级队列的模拟实现
namespace myPriorityQueue
{
template<class T,class Container=vector<T>,class Compare=Less<T>>
class Priority_queue
{
public:
Priority_queue()
{
}
template<class Iterator>
Priority_queue(Iterator first,Iterator last)
{
while (first != last)
{
_con.push_back(*first);
first++;
}
for (int i = (_con.size() - 1 - 1) / 2; i > 0; i--)
{
AdjustDown(i);
}
}
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
T& top()
{
return _con[0];
}
bool empty()
{
return _con.empty();
}
size_t size()
{
return _con.size();
}
private:
void AdjustDown(int parent)
{
Compare com;
size_t child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
{
child++;
}
if (com(_con[parent], _con[child]))
{
swap(_con[parent],_con[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void AdjustUp(int child)//向上调整法
{
Compare com;
int parent = (child - 1) / 2;
while (child>0)
{
if (com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
Container _con;
};
}
我们用容器的适配器来,控制堆的实现,我们通过向上调整法和向下调整法建队,这样就很容易,然后实现其他内容的函数,下面就是仿函数的实现
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
class Greater
{
public:
bool operator()(const T &x, const T &y)
{
return x > y;
}
};
这样就能控制这个优先级队列是大根堆还是小根堆。
3.反向迭代器
在我们使用vector,list等容器的时候,发现源代码,支持了反向迭代器,也就是rbegin,rend,也就是正向迭代器的反转,所以我们实现的时候也是使用内容适配器来完成。
namespace mycode
{
template<class Iterator, class Ref, class Ptr > //
struct ReverseIterator
{
typedef ReverseIterator<Iterator, Ref, Ptr> Self;
Iterator _it;
ReverseIterator(Iterator it)
:_it(it)
{}
Ref operator*()
{
Iterator tmp=_it;
return *(--tmp);
}
Self operator++()
{
_it--;
return *this;
}
Self operator--()
{
_it++;
return *this;
}
Ptr operator->()
{
return &(operator * ());
}
bool operator!=(const Self& it) const
{
return _it != it._it;
}
};
};
在这里我们在使用的时候,用迭代器初始化的时候,解引用的时候需要--tmp,因为rend()是在后面的一个位置,所以--就可以错开,实现完美遍历。
template<class T>
class list
{
typedef list_node<T> Node;
public:
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
}