今天在刷leetcode23题时发现,在使用优先队列合并时,创建了一个结构体内嵌比较函数,很有意思,便做如下记录:
struct Status {
int val;
ListNode *ptr;
bool operator < (const Status &rhs) const {
return val > rhs.val;
}
};
1. 为什么设三个参数?
要知道status里为什么要放三个参数,这和c++的优先队列的定义有关:
priority_queue<Type, Container, Functional>
int val参数就是type,也就是需要存放数据的数据类型,这里放的是ListNode的val,也是优先队列排序所需要用到的参数;
ListNode也就是container,指数据是如何存放,比如还有vector还是deque;这两个就好比 vector<int>,第一个参数放的int,第二个参数放的vector。
Functional就是放的函数参数,在代码段中就是指操作符 < 重载。
2. 重载操作符的函数两个const都是什么意思?
第一个const 是为了保证引用传递进来的参数不被修改,我们知道传递有value pass和refer. pass,如果传进来的是引用,那么在函数内部可能会使其修改,而此处是重载<操作符,故用const。
第二个const 是为了防止出现二义性,如果没写const,那再body外调用时如果使用了const,则会出现二义性,此处由于是看不出来,但是在有构造函数初始化是就特别明显,如:
class complex
{
public:
complex (double r = 0, double i = 0): re (r), im (i) { }
double real () const { return re; }
double imag () const { return im; }
private:
double re, im;
};
如果在调用时:complex complex c1(2,1);则会发现,构造函数里给了初始化,这里也给了初始化,如果没加const,那么real函数是跟着(0,0)还是(2,1)呢?
3. 结构体内嵌比较函数的含义
3.1 优先队列和一般的sort()不同的是,sort是从小到大排序,而优先队列是默认从大到小排列,故需对<号进行>号处理
3.2 对于:
statu s1,s2;
s1<s2;
s1就是指代码里的val,s2就是指代码里的const Status &rhs,故val>rhs就是指这个意思啦!
4. leetcode23题答案详解
class Solution {
public:
//优先队列法
struct status{
int val;
ListNode *ptr;
bool operator< (const status &r)const{
return val>r.val;
}
};
priority_queue<status> qu;
ListNode* mergeKLists(vector<ListNode*>& lists) {
for(auto i:lists){
if(i)qu.push({i->val,i});
}
//把每一个链表的头结点插入优先队列,队列里会按val的值进行排序
ListNode *dummy=new ListNode(-1);
ListNode *p=dummy;
//虚拟头结点,用来记录答案
while(!qu.empty()){
auto f=qu.top();
qu.pop();
p->next=f.ptr;
//qu.top()一定会是最小的!
if(f.ptr->next!=nullptr){
//如果f.ptr的next还有东西,则把它的子节点输入到优先队列里
//优先队列又会按val值进行排序
qu.push({f.ptr->next->val,f.ptr->next});
}
p=p->next;
//移动到下一个节点
}
return dummy->next;
}
};