c++中的std::set,是基于红黑树的平衡二叉树的数据结构实现的一种容器,因为其中所包含的元素的值是唯一的,因此主要用于去重和排序。这篇文章的目的在于探讨和分享如何正确使用std::set实现去重和排序功能。

  1.方法一:使用std::set内置的less比较函数(直接定义内置类型的set对象)

   这种方法适用于:1)比较int、char等内置类型。2)只能针对某一个内置类型去重和排序:如果想通过id(int)去重,并通过hot(int)排序,该种方法就束手无策了。代码如下:

 #include <iostream>
#include <set>
using namespace std;
void main()
{
std::set<int> mySet; // 直接定义内置类型set集合
mySet.insert(); // 默认比较函数为less
mySet.insert(); // 从小到大排序
for(auto it:mySet)
{
std::cout<<it<<std::endl;
}
std::cout<<"end"<<std::endl; }
结果如下:
output: end

  2.方法二:自定义类(结构体)比较函数

    前文提到:直接定义内置类型的set对象,即使用std::set内置的默认的less比较函数,可能不能满足我们的实际需求。例如:现在有一批结构体对象,需要将其插入set集合,并按照id去重,按照热度hot进行排序。这个时候,就需要重新自定义比较函数了。有两种方法可以自定义比较函数:

  2.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 m_id;
int m_hot;
song(int id,int hot)
{ this->m_id = id;
this->m_hot = hot;
}
bool operator<(const struct song & right)const //重载<运算符
{
if(this->m_id == right.m_id) //根据id去重
return false;
else
{
if(this->m_hot != right.m_hot)
{
return this->m_hot > right.m_hot; //降序
}
else
{
return this->m_id > right.m_id;
}
}
}
};
void main()
{
std::set<song> mySet;
song s1(,);
song s2(,);
song s3(,);
song s4(,);
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.m_id<<",hot:"<<it.m_hot<<std::endl;
}
std::cout<<"end"<<std::endl;
};
结果如下:
id:,hot :
id:,hot :
id:,hot : 100
end

2.2 重载()运算符

     具体代码如下:

 #include <iostream>
#include <set>
using namespace std;
struct song
{
int m_id;
int m_hot;
song(int id,int hot)
{ this->m_id = id;
this->m_hot = hot;
}
/*
bool operator<(const struct song & right)const //重载<运算符
{
if(this->m_id == right.m_id) //根据id去重
return false;
else
{
if(this->m_hot != right.m_hot)
{
return this->m_hot > right.m_hot; //降序
}
else
{
return this->m_id > right.m_id;
}
}
}
*/
};
struct comp
{
bool operator()(struct song left,struct song right) //重载()运算符
{ if(left.m_id == right.m_id) //根据id去重
return false;
else
{
if(left.m_hot != right.m_hot)
{
return left.m_hot > right.m_hot; //降序
}
else
{
return left.m_id > right.m_id;
} }
} };
void main()
{
std::set<song,comp> mySet; //写法和2.1中的的区别
song s1(,);
song s2(,);
song s3(,);
song s4(,);
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.m_id<<",hot:"<<it.m_hot<<std::endl;
}
std::cout<<"end"<<std::endl;
};
结果如下:
id:30,hot : 200
id:20,hot : 200
id:10,hot : 100
end

    

c++中std::set自定义去重和排序函数的更多相关文章

  1. python中sorted()和set()去重,排序

    前言 在看一个聊天机器人的神经网络模型训练前准备训练数据,需要对训练材料做处理(转化成张量)需要先提炼词干,然后对词干做去重和排序 words = sorted(list(set(words))) 对 ...

  2. FCL源码中数组类型的学习及排序函数Sort函数的分析

    Array 是所有数组的基类ArrayList 解决了所有Array 类的缺点    能动态扩容, 但是类型不安全的,而是会有装箱与拆箱的性能开销List<T> 则是解决了ArrayLis ...

  3. 重写Oracle的wm_concat函数,自定义分隔符、排序

    oracle中,wm_concat函数是一个聚合函数,和mysql中的group_concat函数类似,不过group_concat函数比较强大,可以定义分隔符和排序,当然所谓强大是相对的,这里假使我 ...

  4. MapReduce自定义二次排序流程

    每一条记录开始是进入到map函数进行处理,处理完了之后立马就入自定义分区函数中对其进行分区,当所有输入数据经过map函数和分区函数处理完之后,就调用自定义二次排序函数对其进行排序. MapReduce ...

  5. PHP常用数字函数以及排序函数

    一:数字函数 .ceil() 进一取整 示例:ceil(0.9) 结果为1 .abs() 绝对值 示例:abs(-1) 结果为1 .rand() 随机数 示例:rand(1. 100) 1到100 以 ...

  6. java中List对象列表去重或取出以及排序

    面试碰到几次list的去重和排序.下面介绍一种做法: 1. list去重 1.1 实体类Student List<Student>容量10k以上,要求去重复.这里Student的重复标准是 ...

  7. 一个std::sort 自定义比较排序函数 crash的分析过程

    两年未写总结博客,今天先来练练手,总结最近遇到的一个crash case. 注意:以下的分析都基于GCC4.4.6 一.解决crash 我们有一个复杂的排序,涉及到很多个因子,使用自定义排序函数的st ...

  8. 【转载】C#中自定义Sort的排序规则IComparable接口

    C#中的List集合在排序的时候,如果不使用Lambda表达式进行排序的话,一般调用Sort()方法进行排序,如果希望Sort()方法排序后的结果跟我们预想的效果一致或者按照我们自定义的规则排序,则需 ...

  9. vector中数据进行去重和排序

    , , , , , , ,}; std::vector<int> vec(a, a+sizeof(a)/sizeof(int) ); std::sort(vec.begin(), vec. ...

随机推荐

  1. CentOS 安装Oracle 11g R2

    CentOS 安装Oracle 11g R2 学习了-/ https://www.osyunwei.com/archives/5445.html

  2. 12、Java并发性和多线程-Java同步块

    以下内容转自http://ifeve.com/synchronized-blocks/: Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免 ...

  3. docker: 定时检查docker container的运行状态并发邮件报警

    首先创建一个发送邮件的bash脚本 - send_mail.sh: #!/bin/bash curl -s --user 'api:key-xxxxxxxxxxxxx' \ https://api.m ...

  4. lua中的闭包小结

    function newCounter() return function() i=i+ return i end end c1=newCounter() print(c1()) print(c1() ...

  5. Linux C 网络编程——多线程的聊天室实现(server端)

    server端的主要功能: 实现多用户群体聊天功能(此程序最多设定为10人.可进行更改),每一个人所发送的消息其它用户均能够收到.用户能够任意的增加或退出(推出以字符串"bye"实 ...

  6. Hibernate基于注解的双向one-to-many映射关系的实现

    在项目中用到了一对多的实体类关系映射,之前接触的都是基于配置文件的映射实现.可是公司的大部分都是基于注解的.因此自己參考之前的代码捣鼓了基于注解的一对多的映射关系实现. 背景: 一的一端:QingAo ...

  7. LeetCode 171. Excel Sheet Column Number (Excel 表格列数字)

    Related to question Excel Sheet Column Title Given a column title as appear in an Excel sheet, retur ...

  8. JMeter常用函数 使用图解

    函数的调用都是以${__function()}这种形式开始的注意:“__”是两个英文下划线 __UUID 生成唯一字符串

  9. android 之WebView

    (一)使用中遇到的问题: 1.解决webview缓存: WebSettings.LOAD_NO_CACHE   或者直接清除缓存 webView.getSettings().setCatchMode( ...

  10. JSP-Runoob:JSP 服务器响应

    ylbtech-JSP-Runoob:JSP 服务器响应 1.返回顶部 1. JSP 服务器响应 Response响应对象主要将JSP容器处理后的结果传回到客户端.可以通过response变量设置HT ...