std::set自定义排序比较函数

std::set默认是通过std::less函数来比较key值的。

#include <iostream>
#include <set>


void main()
{
    std::set<int> mySet;    //
    mySet.insert(10);       // 默认比较函数为less
    mySet.insert(20);       // 从小到大排序
    for(auto it:mySet)
    {
        std::cout<<it<<std::endl;
    }

    return 0;
}

自定义类(结构体)比较函数

1. 重载<操作符

为甚么要重载<运算符呢?能不能重载"<="或者">="运算符?答案是不可以。几乎所有的方法或容器都需要排序来满足数学意义上的标准严格弱序化,否则这些方法或容器的行为将不可预知。假设f(x,y)是一个比较函数。 如果该函数满足如下条件则它是严格弱序化的。

      1.f(x,x) = false; 

    2. if f(x,y) then !f(y,x)

    3.if f(x,y) and f(y,z) then f(x,z)

    4. if !f(x,y)&&!f(y,x) then x==y; if x==y and y==z then x==z;

看上去有点晕乎,不过不用担心,只要你的比较方法能够满足对相等元素永远返回false(记住一个准则:永远让比较函数对相同元素返回false),那你的方法就满足要求了。

    其实,set容器在判定已有元素a和新插入元素b是否相等时,是这么做的:1)将a作为左操作数,b作为有操作数,调用比较函数,并返回比较值  2)将b作为左操作数,a作为有操作数,再调用一次比较函数,并返回比较值。如果1、2两步的返回值都是false,则认为a、b是相等的,则b不会被插入set容器中;如果1、2两步的返回值都是true,则可能发生未知行为,因此,记住一个准则:永远让比较函数对相同元素返回false。

#include <iostream>
#include <set>
using namespace std;
struct song
{
	int id;
	int hot;
	song(int id, int hot)
	: id{id}
	, hot{hot}
	{}

	bool operator<(const song& right)const   //重载<运算符
	{
		if (id == right.id)     //根据id去重
			return false;
		else
		{
			if (hot != right.hot)
			{
				return hot > right.hot;      //降序
			}
			else
			{
				return id > right.id;
			}
		}
	}
};
int main()
{
	std::set<song> mySet;
	song s1(10, 100);
	song s2(20, 200);
	song s3(20, 300);
	song s4(30, 200);

	mySet.insert(s1);    //插入s1
	mySet.insert(s2);    //插入s2
	mySet.insert(s3);    //s3和s2的id相同,不插入
	mySet.insert(s4);    //插入s4

	for (auto it : mySet)
	{
		std::cout << "id:" << it.id << ",hot:" << it.hot << std::endl;
	}
	
	return 0;
};

重载()运算符

#include <iostream>
#include <set>

struct song
{
	int id;
	int hot;
	song(int id, int hot)
	: id{ id }
	, hot{ hot }
	{}
};
struct comp
{
	bool operator()(const song& left, const song& right) const //重载()运算符
	{

		if (left.id == right.id)     //根据id去重
			return false;
		else
		{
			if (left.hot != right.hot)
			{
				return left.hot > right.hot;      //降序
			}
			else
			{
				return left.id > right.id;
			}
		}
	}

};

int main()
{
	std::set<song, comp> mySet;      //写法和2.1中的的区别
	song s1(10, 100);
	song s2(20, 200);
	song s3(20, 300);
	song s4(30, 200);

	mySet.insert(s1);    //插入s1
	mySet.insert(s2);    //插入s2
	mySet.insert(s3);    //s3和s2的id相同,不插入
	mySet.insert(s4);    //插入s4

	for (auto it : mySet)
	{
		std::cout << "id:" << it.id << ",hot:" << it.hot << std::endl;
	}

	return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值