关于c++中std::set自定义去重和排序函数中的错误

来自网上的一篇c++中std::set自定义去重和排序函数博文中的去重方法存在严重错误(坑害了我很久。。。。。)
其中的方法二:利用重载 < 操作符或重载 () 运算符实现自定义类的排序和去重问题,代码如下:

#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(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.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

代码利用重载 < 操作符,按照song.id查重,按照song.hot排序。然而看似完美的结果其实存在错误,只需要稍微改变一下插入的顺序和输入的数据,就会出现错误:

int main()
{
    std::set<song> mySet;   
    song s1(10,100);
    song s2(20,200);
    song s3(30,200);
    song s4(10,300);
    mySet.insert(s1);    //插入s1
    mySet.insert(s2);    //插入s2
    mySet.insert(s3);    //插入s3
    mySet.insert(s4);    //s4和s1的id相同
    for(auto it:mySet)
    {
        std::cout<<"id:"<<it.m_id<<",hot:"<<it.m_hot<<std::endl;
    }
    std::cout<<"end"<<std::endl;
    return 0;
};

输出的结果为:

id:10,hot:300
id:30,hot:200
id:20,hot:200
id:10,hot:100
end

这里重复插入了两个 id 为 10 的变量,所以该代码其实并不能正确的去重。

大概猜测其原因是,代码按照song.id查重,却按照song.hot排序,而insert方法不是遍历整个容器,而是红黑树的插入操作,因此insert操作按照song.hot排序查找到合适的位置就会直接插入,而不会遍历整个容器去重。

因此,重载自定义类的比较操作只能按照单一的标准进行排序和去重

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值