优先级队列模拟实现
- 1.文档了解
- 2.仿函数实现优先级队列
- 仿函数
- 1.定义
- 2.语法
- 3.使用
- 3.模拟实现源码
1.文档了解
从priority_queue的文档中,我们可以得出以下几点:
1.priority_queue是一个容器适配器
2.priority_queue它实质是一个堆,且默认为大堆
3.对于参数传入的Compare,从字面意思是比较,那么其究竟是什么呢?
2.仿函数实现优先级队列
在实现堆的时候,对于大堆还是小堆的逻辑控制主要是使用push(向上调整算法)和pop(向下调整算法)时,判断父亲位置和孩子位置的大小关系,究竟是父亲大还是孩子大的关系。
对于大堆和小堆类,我们固然可以直接CV一份再将其符号修改,但是两个类的重合度极高,非常的臃肿。那么我们如何通过只实现一个类模板来完成大小堆的通用呢?
我们可以通过仿函数来实现。
仿函数
1.定义
通俗理解,仿函数是对于()的重载,从而达到仿照(类似)函数的行为。其本质就是运算符的重载。
2.语法
它的语法我们通过一个例子来进行演示。
template<class T>
struct Less
{
public:
bool operator()(T x, T y)
{
return x < y;
}
};
int main()
{
Less<int> ls;
cout << ls(1, 2) << endl; //这里和函数调用很类似
return 0;
}
这里对于对象的使用就和调用函数。函数传参类型。
3.使用
那么我们如何使用仿函数来实现我们上述的需求呢?
以实现大堆的push为例。
//默认大堆的实现
void adjust_up(int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (_con[parent] < _con[child])
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& val)
{
_con.push_back(val);
adjust_up(_con.size() - 1);
}
对于上述的逻辑中,如果需要在一个类中实现大堆的逻辑,我们可以实现判断是否小于的仿函数,然后创建一个该类的对象,这样我们就可以通过该对象来实现仿函数进而替换上述中的比较逻辑。
template<class T>
struct less
{
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
void adjust_up(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[parent] < _con[child])
if (com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
如果需要让大堆和小堆共用一个模板,那么如何控制其逻辑是大于还是小于呢?
我们可以使用模板参数,将仿函数对象作为模板传入,这样我们需要什么样的比较方式,就传入其对应的仿函数,从而让其自己实现比较逻辑。无论是内置类型还是自定义类型,只要我们实现了其逻辑的仿函数,都可以实现大小堆的排列。
template<class T>
struct less
{
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
struct greater
{
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:
void adjust_up(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;
}
}
}
void push(const T& val)
{
_con.push_back(val);
adjust_up(_con.size() - 1);
}
//......
private:
Container _con;
3.模拟实现源码
template<class T>
struct less
{
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
struct greater
{
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T, class Container = vector<T>, class Compare = less<T>>
class priority_queue
{
public:
priority_queue()
{
}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
{
while (first != last)
{
push(*first);
first++;
}
}
void adjust_up(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
//if (_con[child] > _con[parent])
//if (_con[parent] < _con[child])
if (com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void push(const T& val)
{
_con.push_back(val);
adjust_up(_con.size() - 1);
}
void adjust_down(int parent)
{
Compare com;
int 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[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top() const
{
return _con.front();
}
size_t size()
{
return _con.size();
}
bool empty() const
{
return _con.empty();
}
private:
Container _con;
};
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top() const
{
return _con.front();
}
size_t size()
{
return _con.size();
}
bool empty() const
{
return _con.empty();
}
private:
Container _con;
};