map重写比较器

本文详细介绍了如何在C++中为结构体重载比较运算符(< 和 >),以便将结构体用作map的key或放入set中。通过实例展示了如何实现并使用这些自定义比较器,确保数据结构按照特定规则排序。
结构体作为map的key或放入set中,需要重载<运算符,如下:

typedef struct tagRoadKey
{
    int m_i32Type;
    int m_i32Scale;

    bool operator <(const tagRoadKey& other) const // 注意是const函数!!
    {
        if (m_i32Type != other.m_i32Type) // 类型按升序排序
        {
            return (m_i32Type < other.m_i32Type);
        }
        else // 如果类型相同,按比例尺升序排序
        {
            return (m_i32Scale < other.m_i32Scale);
        }
    }

} RoadKey;

也可以重载>运算符,示例如下:

#include <iostream>
#include <string>
#include <map>

using namespace std;

class Array
{
private:
    int m_i32Num1;
    int m_i32Num2;

public:
    Array(int i32Num1, int i32Num2);
    bool operator >(const Array& other) const;
};

Array::Array(int i32Num1, int i32Num2)
{
    m_i32Num1 = i32Num1;
    m_i32Num2 = i32Num2;
}

bool Array::operator >(const Array& other) const
{
    if (m_i32Num1 > other.m_i32Num1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

// 此结构体作为map的value
struct TInfo
{
    int m_i32Num1;
    int m_i32Num2;
};

int main(int argc, char* argv[])
{
    map<Array, TInfo, greater<Array> > stMap;

    TInfo stInfo1 = { 1, 1};
    stMap.insert(pair<Array, TInfo>(Array(1, 2), stInfo1));

    TInfo stInfo2 = { 2, 1, 1 };
    stMap.insert(pair<Array, TInfo>(Array(2, 2), stInfo2));

    TInfo stInfo3 = { 3, 1, 1 };
    stMap.insert(pair<Array, TInfo>(Array(3, 2), stInfo3));

    for (map<Array, TInfo, greater<Array> >::iterator it = stMap.begin(); it != stMap.end(); ++it)
    {
        cout << it->second.m_i32Num1 << endl;
    }

    return 0;
}
说明:
 map缺省是用less<Key>作为比较器,所以它要求作为Key的类要重载“<”操作符,没有重载“<”操作符,而是重载了“>”操作符就会报错。
反之,也可以显式地用greater<Key>作为比较器,此时就必要重载Key类中的“>”操作符了。
附:stl中map和set的声明,二者比较像,底层都是用红黑树实现的

template < class Key, class Compare = less<Key>,
           class Allocator = allocator<Key> > class set;

template < class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key,T> > > class map;
 
template < class Key, class Compare = less<Key>,
           class Allocator = allocator<Key> > class multiset;
 
template < class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key,T> > > class multimap;
 
从上面的声明可以看出,也可以定义一个函数对象Compare,声明map或set类型时传进入,如:

struct TTimeCompare
{
    bool operator ()(const CTimerEvent* po1, const CTimerEvent* po2)const
    {        
        return (po1->m_oNextTick < po2->m_oNextTick);
    }
};

typedef multiset<CTimerEvent*, TTimeCompare> TEventSet;


struct ltstr // less than
{
    bool operator()(const char* s1, const char* s2) const
    {
        return strcmp(s1, s2) < 0;
    }
};




set<const char*, ltstr> stSet; // set<Key, Compare, Alloc>
map<const char*, int, ltstr> stMap; // map<Key, Data, Compare, Alloc>




struct eqstr // equal
{
    bool operator()(const char* s1, const char* s2) const
    {
        return strcmp(s1, s2) == 0;
    }
};


hash_map<const char*, int, hash<const char*>, eqstr> stHashMap;  // hash_map<Key, Data, HashFcn, EqualKey, Alloc>


// 自定义hash函数
namespace std
{
    template<>
    struct hash<KEY_TYPE>
    {
        size_t operator()(const KEY_TYPE& key) const
        {
            //return key.Hash();
        }
    };
}

 相等的时候返回false,否则报错

### C++ 中对 `std::map` 进行自定义排序 在 C++ 的标准库中,`std::map` 是一种关联容器,默认情况下按照键值的升序排列。如果需要实现自定义排序,则可以通过重写比较器来完成这一需求。具体来说,在创建 `std::map` 时可以传入一个自定义的比较函数或 functor 来替代默认的 `<` 操作符。 以下是详细的说明以及代码示例: #### 自定义比较器的方式 为了改变 `std::map` 的排序方式,可以在实例化 `std::map` 时提供第三个模板参数作为比较器[^5]。这个比较器可以是一个函数对象 (functor),也可以是一个 Lambda 表达式或者指向函数的指针。 #### 使用 Functor 实现自定义排序 Functor 是一种实现了调用操作符 (`operator()`) 的类。通过定义一个 Functor 并将其传递给 `std::map`,我们可以轻松地控制其内部存储顺序。 ```cpp #include <iostream> #include <map> struct CustomComparator { bool operator()(const int& lhs, const int& rhs) const { // 定义降序排序逻辑 return lhs > rhs; } }; int main() { std::map<int, std::string, CustomComparator> myMap; myMap[1] = "one"; myMap[2] = "two"; myMap[3] = "three"; for (const auto& pair : myMap) { std::cout << pair.first << ": " << pair.second << "\n"; } return 0; } ``` 上述代码展示了如何利用 Functor 对整数类型的键按降序方式进行排序[^6]。 #### 使用 Lambda 表达式简化比较器C++11 开始支持 Lambda 表达式,它能够进一步简化比较器的编写过程。下面的例子演示了如何使用 Lambda 表达式代替传统的 Functor 结构体。 ```cpp #include <iostream> #include <map> int main() { auto cmpLambda = [](const int& lhs, const int& rhs) -> bool { return lhs > rhs; // 定义降序排序逻辑 }; std::map<int, std::string, decltype(cmpLambda)> myMap(cmpLambda); myMap[1] = "one"; myMap[2] = "two"; myMap[3] = "three"; for (const auto& pair : myMap) { std::cout << pair.first << ": " << pair.second << "\n"; } return 0; } ``` 此方法更加简洁明了,并且避免了额外定义独立的结构体或类[^7]。 #### 总结 无论是采用 Functor 或者 Lambda 表达式的解决方案都可以有效地满足对于 `std::map` 键值不同排序的需求。需要注意的是,一旦选择了特定的比较规则之后就不能再更改该规则;因此建议在设计阶段就明确所需的排序策略[^8]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值