最近在写一些算法,其中用到了优先队列,由于优先队列默认的比较函数难以满足较为复杂的类型。同时也需要在一些算法中快速使用比较器进行排序。所以不难免会自己写比较器,以此来实现大根堆或者小根堆。
该文主要是为了记录一下比较器的写法与使用方法,以后用到时方便查阅,防止遗忘。
目前我只写过两种比较器:(以后用到新的写法会及时更新)
- 在原结构体类型中重载运算符
- 重新定义一个结构体,并在结构体中只需重载运算符
一、在原结构体类型中重载运算符
struct Meeting{
float start_time;
float end_time;
Meeting(float start, float end) {
start_time = start;
end_time = end;
}
bool operator < (const Meeting & meet) const {
return this->end_time < meet.end_time;
}
};
代码如上所示,结构体Meeting有两个成员变量。这里要注意的就是这两个const,重载运算符中第一个const代表该函数不会修改被显式访问的对象,第二个const代表该函数不会修改被隐式访问的对象。
另外,return当中小于号代表的是大根堆,大于号代表的是小根堆。
在优先队列中的使用方式:
priority_queue<Meeting, vector<Meeting>> meeting_heap;
也可以调用stable_sort对vector进行排序:
vector<Meeting> meetings;
//...emplace_back操作...//
stable_sort(meetings.begin(), meetings.end());
二、重新定义一个结构体,并在结构体中只需重载运算符
struct Project{
int cost;
int profit;
Project(int c, int p){
cost = c;
profit = p;
}
};
struct cmp_cost{//小根堆
bool operator () (const Project & p1, const Project & p2) {
return p1.cost > p2.cost;
}
};
struct cmp_profit{//大根堆
bool operator () (const Project & p1, const Project & p2) {
return p1.profit < p2.profit;
}
};
代码如上所示,结构体Project中有两个成员变量。
而对于比较器我们只需要在结构体外重新定义结构体,并在结构体中只需重载()运算符,同样两个const代表不会修改所访问的对象,小于号代表大根堆,大于号代表小根堆。
在优先队列中使用方法:
priority_queue<Project, vector<Project>, cmp_cost> cost_heap;
priority_queue<Project, vector<Project>, cmp_profit> profit_heap;
三、匿名函数(Lambda表达式)
auto cmp = [](int a, int b){ return a > b; }; // 小根堆
// auto cmp = [](int a, int b){ return a < b; }; // 大根堆
priority_queue<int, vector<int>, decltype(cmp)> q(cmp);
建议去看下源码,更能理解不同的写法