首页 > 其他分享 >set通过operator <去重、排序

set通过operator <去重、排序

时间:2023-10-10 23:23:31浏览次数:32  
标签:set 20 song mySet hot right operator 排序 id

如何定义类的operator<以保证set去重、有序

STL 自定义比较器的要求是必须为严格弱序,因为STL内部就是这样做的。

  1. x<x 为假 (反自反)
  2. x<y 为真则y<x 为假 (反对称)
  3. x<y 且y<z 则x<z (传递性)
  4. x<y 为假且y<x 为假,y<z 为假且z<y 为假,则x<z 为假且z<x 为假 (不可比的传递性)

如果两个关键字都不严格弱序于另一个,则这两个关键字相等。
如果!(a<b)&&!(b<a),就认为a和b相等,这样就可以保证去重。
在使用set存储自定义类时,重载的operator<兼具了排序和去重的功能,然而使用不当很容易带来错误。

先说结论:
operator<中去重的关键字和排序的关键字必须是相同的(可以是一个或者多个),否则会出现错误。因为红黑树的插入并不会遍历容器中所有的元素,而是根据operator<的返回值来判断插入的位置,关键字相同的元素也许在插入时并不会比较,而是位于不同分支上,导致并未去重。

一个反例

#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;     
            }
        }
        if(this->m_id==right.m_id)
            return this->m_hot<right.m_hot;
        else
            return this->m_id<right.m_id;
    }
};
int main()
{
    std::set<song> mySet;
    song s1(10,100);
    song s2(20,200);
    song s3(20,50);
    song s4(30,200);
    mySet.insert(s1);
    mySet.insert(s2);
    mySet.insert(s3);    
    mySet.insert(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
id:20,hot:50
end
*/

出错的原因就是
s1(10,100) < s2(20,200),s4(20,50) < s1(10,100)
但s2(20,200) < s4(20,50)不成立,即不满足传递性,导致二者位于二叉树不同分支,插入时并未遍历到等价的元素,因此看起来与期望的去重不符。

标签:set,20,song,mySet,hot,right,operator,排序,id
From: https://www.cnblogs.com/wangerblog/p/17756009.html

相关文章

  • 拓扑排序学习笔记
    拓扑排序-oiwiki在有向无环图中,若一个由该图中所有点构成的序列满足:图中所有边(x,y),x在序列A中都出现在y前,则称A是该图的一个拓扑序。求解序列A的过程就叫拓扑排序。拓扑排序可以解决一个有向无环图的所有节点排序。我理解的话,就是按每个店的入度多少的顺序找到一......
  • Django-setting配置不当引起的Session反序列化
    Django-setting配置不当引起的Session反序列化在复现ez_py这道题的时候,翻到了p神19年写的一篇文章:https://www.leavesongs.com/PENETRATION/code-breaking-2018-python-sandbox.html,特此做了下笔记漏洞成因漏洞成因位于目标配置文件settings.py下关于这两个配置项SESSION_EN......
  • SQLAlchemy学习-12.查询之 order_by 按desc 降序排序
    前言sqlalchemy的query默认是按id升序进行排序的,当我们需要按某个字段降序排序,就需要用到order_by。order_by排序默认情况下sqlalchemy的query默认是按id升序进行排序的res=session.query(Project).all()print(res)#[<Project(id='1',project_name='string'.........
  • Python 常见排序:冒泡、选择、快速
    简单说明:1.冒泡排序:双层循环,交替结果2.选择排序:whilenums,假设第一个值为做小,通过for循环找到最小值以此来替换,再将nums中该值去掉继续上述步骤3.快速排序:定义一个初值,把整个数据列表分为两部分,再递归代码实现:#冒泡排序defaction1(n):foriinrange(len(n)):......
  • 归并排序
    一、算法描述归并排序,是创建在归并操作上的一种有效的排序算法。算法是采用分治法的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。思路如下:取分界点,intmid=(l+r)/2......
  • abp 框架使用自定义appsetings.json
    定义一个自定义的配置文件在调试配置中设置启动环境这里的值填入刚刚设置的配置文件appsetings.{配置文件名字}.json的配置文件名字启动即可系统启动时,首先会检查{配置文件名字}是否存在,存在的话使用appsettings.{配置文件名字}.json,不存在则使用appsettings.json(默认配......
  • [abc302f] Merge Set
    F-MergeSet显然要建图首先,我们有一个粗略的想法,对于同一集合\(S_i\)内的元素,\(S_{i,j}\)与\(S_{i,j+1}\)间连一条无向的标号为\(i\)的边那么题目显然是要我们跑最短路,若到达\(x\)的边为\(i\),然后从\(x\)向外走到点\(y\),走的边若还为\(i\),那么代价为\(0\),否则代价为\(1\)也......
  • java stream 操作map根据key或者value排序的实现
    javastream操作map根据key或者value排序的实现publicclassTest02{publicstaticvoidmain(String[]args){List<FundBenchMarkInfo>fundBenchMarkList=newArrayList<>();fundBenchMarkList.add(newFundBenchMarkInfo("2",new......
  • JavaSE---SortedSet(TreeSet)
    SortedSet概述A{@linkSet}thatfurtherprovidesatotalorderingonitselements.提供元素排序的set;Theelementsareorderedusingtheir{@linkplainComparablenatural ordering},orbya{@linkComparator}typicallyprovidedatsortedsetcre......
  • setting.xml文件配置释义
    maven下载jar规则maven下载jar包优先从配置的本地仓库localRepository查找jar,找不到会去配置的远程仓库中下载jar配置的远程仓库都有对应的id,可以根据标签填对应的仓库的id,代表,从这个仓库下载jar的时候,会走对应的镜像如果下载不到jar,会报错plugin会从配置的pluginRepositor......