自定义排序、结构体/优先队列 重载小于或大于号

数组一般的sort排序

#include<iostream>
#include<algorithm>

using namespace std;

int a[10]={5,1,8,4,2,5,7,4,9,10};

int main(){
    int i;
    sort(a,a+10);
    for(int i=0;i<10;i++){
        cout<<a[i]<<" ";
    }
    return 0;
}
//输出:1 2 4 4 5 5 7 8 9 10

数组自定义使用cmp仿函数

#include<iostream>
#include<algorithm>

using namespace std;

int a[10]={5,1,8,4,2,5,7,4,9,10};
//这里是从大到小排序
bool cmp(const int &a,const int&b){
    return a>b;
}

int main(){
    int i;
    sort(a,a+10,cmp);
    for(int i=0;i<10;i++){
        cout<<a[i]<<" ";
    }
    return 0;
}

//输出:10 9 8 7 5 5 4 4 2 1 %

结构体排序

重载小于号有两种方式,作为类的成员函数,或者用友元friend,
作为成员函数时,有隐士的this指针,只有一个参数;
用friend友元时,没有this指针,用两个参数;

#include<iostream>
#include<algorithm>
using namespace std;

/* 排序规则:优先按照a从小到大排序,如果a相等,按照b从小到大排序 */
#if 0
struct node{
    int a,b;
    bool operator<(const node& B){
        if(a!=B.a) return a<B.a;
        return b<B.b; 
    }
};
#endif

struct node{
    int a,b;
    friend bool operator<(node& A,node& B){
        if(A.a != B.a) return A.a < B.a;
        return A.b < B.b;
    }
};
node a[10]={ {2,3},{10,10},{5,5},{4,4},{10,4},{7,1},{10,9},{4,6},{10,7},{2,8}};

int main(){
    sort(a,a+10);
    for(int i=0;i<10;i++){
        cout<<a[i].a<<" "<<a[i].b<<endl;
    }
    return 0;
}



#include<iostream>
#include<algorithm>
using namespace std;

struct node{
    int a,b;
};
node a[10]={ {2,3},{10,10},{5,5},{4,4},{10,4},{7,1},{10,9},{4,6},{10,7},{2,8}};

bool cmp(node& A,node& B){
    if(A.a!=B.a) return A.a<B.a;
    return A.b<B.b;
}

int main(){
    sort(a,a+10,cmp);
    for(int i=0;i<10;i++){
        cout<<a[i].a<<" "<<a[i].b<<endl;
    }
    return 0;
}

//输出结果:
2 3
2 8
4 4
4 6
5 5
7 1
10 4
10 7
10 9
10 10

优先队列重载小于号

struct point{  
    int x;  
    int y;  
    int val;  
    friend bool operator < (point a, point b)  
    {  
        return a.val > b.val;    //重载小于号使得小的先出队列  
    }  
};  
priority_queue<point ,vector<point>,less<point>>pri;/* 默认为大顶堆 */

在此处定义一个优先队列大顶堆:priority_queuepri;

如果要按照以val的值进行从小到大排列,操作如上。重载<操作符。

意思是如果a.val > b.val成立,那么结构体point a < point b成立。由于优先队列大顶堆是按照从大到小排列,所以结构体b会排列到a之前,然而b.val是最小的,所以实现了按照val的从小到大排序。

总结:对于优先队列默认大顶堆,如果想让较小val的先出去,则让较大Point的val值较小即可;

应用实例:

N*M的矩阵,有N个递增的有序数组,每个数组长度为M,合并所有的数,找出前k个最小的元素;

输入:
3 3
4
[[1,4,5],[2,4,6],[3,5,7]];
3行3列的举证,k = 4,求最小的前4个元素
输出:
1,2,3,4;

代码实现

#include<bits/stdc++.h>

using namespace std;

const int N = 10000;
const int M = 10000;


struct Point{
    int x,y;
    int val;
    friend bool operator > (Point p1,Point p2){
        /* 要想p1 > p2 ,则要p1的val值大于p2的val值 */
        return p1.val > p2.val; /* 按照val值的大小排,小的在小顶堆的堆顶 */
    }
};

vector<int>help(vector<vector<int>>& matrix,int k){
    vector<int>ans;
    priority_queue<Point,vector<Point>,greater<Point> >p; /* 小顶堆(greater),默认为大顶堆(less) */
    for(int i = 0 ; i < matrix.size(); i++){
        p.push(Point{i, 0 ,matrix[i][0]});
    }
    while(p.size() != 0){
        Point minPoint = p.top();
        ans.push_back(minPoint.val);
        p.pop();
        if(ans.size() == k) break;
        if(minPoint.y + 1 < matrix[0].size()){
            p.push(Point{minPoint.x,minPoint.y + 1, matrix[minPoint.x][minPoint.y + 1]});
        }
    }
    return ans;
}

int main(){
    int n ,m ,k;
    cin >> n >> m;
    cin >> k;
    vector<vector<int>>matrix(n ,vector<int>(m,0));
    for(int i = 0 ;i < n; i++){
        for(int j = 0; j < m ;j++){
            int temp;
            cin >> temp;
            matrix[i][j] = temp;
        }
    }
    auto res = help(matrix,k);
    for(auto &v : res){
        cout << v << " ";
    }
    return 0;
}

注意:小顶堆(greater)只能从重载大于号,大顶堆(less)只能重载小于号
即以上代码用

 priority_queue<Point,vector<Point>,less<Point> >p;//(大顶堆)
 struct Point{
    int x,y;
    int val;
    friend bool operator < (Point p1,Point p2){
        /* 要想p1 < p2 ,则要p1的val值小于p2的val值 */
        return p1.val > p2.val; /* 按照val值的大小排,小的在小顶堆的堆顶 */
    }
};

大顶堆较大的在前面,但是按照val值排序。如果想让较小val的先出去,则较大的Point的val应该较小;这种方式也是可行的,注意理解;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值