c++ map 使用自定义结构做关键字

map在STL中的定义

template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>

 第一个参数Key是关键字类型

第二个参数T是值类型

第三个参数Compare是比较函数(仿函数)

第四个参数是内存配置对象

map内部存储机制实际是以红黑树为基础,红黑树在插入节点时,必须依照大小比对之后在一个合适的位置上执行插入动作。所以作为关键字,起码必须有“<”这个比较操作符。我们知道,int,float,enum,size_t等等简单关键字,都有内置的比较函数,与map搭配无论是插入还是查找,都没什么问题。但是作为复杂数据类型,如果没有明确定义“<”比较操作符,就不能与map直接搭配使用,除非我们自己定义第三个参数。

在选择map的关键字时,注意以下两点,同时这两点也是改错的方法:

a) 关键字明确定义“<”比较操作符

b) 没有“<”比较操作符,自定义仿函数替代第三个参数Compare,该仿函数实现“()”操作符,提供比较功能。插入时各节点顺序以该仿函数为纲。

以std::pair为关键字掺入map
下面我们先写一个有错误的函数,在分析错误原因之后,逐步进行修正。

#include <map>
int main()
{
       std::map<std::pair<int, int>, int> res;
       res.insert(std::make_pair(12,33), 33);
}

 这个程序一定失败,如果非要如此使用,上述a方法显然不适合,std::pair是已定义好的结构体不可修改。只能使用b方法了,定义一个比较类改造如下:

    #include <map>  
      
    struct comp  
      
    {  
      
           typedef std::pair<int, int> value_type;  
      
           bool operator () (const value_type & ls, const value_type &rs)  
      
           {  
      
                  return ls.first < rs.first || (ls.first == rs.first && ls.second < rs.second);  
      
           }  
      
    };  
      
    int main()  
      
    {  
      
           std::map<std::pair<int, int>, int, comp> res;  
      
           res.insert(std::make_pair(std::make_pair(12,33), 33));  
      
           res.insert(std::make_pair(std::make_pair(121,331), 331));  
      
           res.insert(std::make_pair(std::make_pair(122,332), 332));  
      
            
      
           std::map<std::pair<int, int>, int, comp>::iterator it = res.find(std::make_pair(121,331));  
      
           if (it == res.end())  
      
                  printf("NULL"n");  
      
           else  
      
                  printf("%d %d %d "n", it->first.first, it->first.second, it->second);  
      
        return 0;  
      
    }  

以结构体或类为关键字插入map

    #include <map>  
      
    struct st  
      
    {  
      
           int a, b;  
      
           st():a(0), b(0){}  
      
           st(int x, int y):a(x), b(y){}  
      
    };  
      
    int main()  
      
    {  
      
           std::map<struct st, int> res;  
      
           res.insert(std::make_pair(st(1,2), 12));  
      
           res.insert(std::make_pair(st(30,4), 34));  
      
           res.insert(std::make_pair(st(5,6), 56));  
      
            
      
           std::map<struct st, int>::iterator it = res.find(st(30,4));  
      
           if (it == res.end())  
      
                  printf("NULL"n");  
      
           else  
      
                  printf("first:%d second:%d %d"n", it->first.a, it->first.b, it->second);  
      
           return 0;  
      
    }  

编译这个程序也是错误的,错误意思大概也是没有定义“<”比较函数。因为struct st是我们自己定义的结构体,所以修改这个程序可以使用上面ab两种方法。我们先谈第一种,第一次修改时我也搞错了,我是这样定义比较函数的。

    struct st  
      
    {  
      
           int a, b;  
      
           st():a(0), b(0){}  
      
           st(int x, int y):a(x), b(y){}  
      
    bool operator < (const struct st &rs) {return (this->a < rs.a || (this->a == rs.a && this->b < rs.b));}  
      
    };  

按照这个改动再次编译程序还是错误,有个如下这样的提示:

/usr/include/c++/3.2.3/bits/stl_function.h:197: passing `const st' as `this' argument of `bool st::operator<(const st&)' discards qualifiers

   为什么会出现这个 问题呢?我们深入STL的源代码看下。既然说是/usr/include/c++/3.2.3/bits/stl_function.h的197行出了问题,且看这行是什么。

// One of the @link s20_3_3_comparisons comparison functors@endlink.

    template <class _Tp>

    struct less : public binary_function<_Tp,_Tp,bool>

    {

         bool operator()(const _Tp& __x, const _Tp& __y) const { return __x < __y; }

     };

 

struct st中的“<”在编译后真正是什么样子呢?大概是bool operator < (struct st &ls, const struct st &rs)。在less调用这个比较符时,它都是以const方式传入,不可能再以非const方式调用,故出错。修正如下

struct st

{

       int a, b;

       st():a(0), b(0){}

       st(int x, int y):a(x), b(y){}

       friend bool operator < (const struct st &ls, const struct st &rs);

};

inline bool operator < (const struct st &ls, const struct st &rs)

{return (ls.a < rs.a || (ls.a == rs.a && ls.b < rs.b));}

 以友联函数代替函数内部定义的比较操作符,STL内部也多是以这种方式定义的。如果我非要以内部定义的方式呢?可以使用b方法,我们自定义一个比较仿函数,替代默认的less。

插入函数返回值
       在map容器中插入数据有很多函数可用,这里只讨论最普通的insert操作,在STL中它是这样定义的。

       pair<iterator, bool> insert(const value_type& x);

       map容器不允许键值重复,在执行插入操作后,可以凭借该返回值获取操作结果。返回值是一个迭代器和布尔值的键值对,迭代器指向map中具有该值的元素,布尔值表示是否插入成功。如果布尔值为true,表示插入成功,则迭代器为新插入值在map中的位置;布尔值为false,表示插入失败(已经存在该值),迭代器为原有值在map中的位置。

    #include <map>  
    #include <iostream>  
    using namespace std;  
      
    class Key  
    {  
    public:  
        Key();  
        Key(int v);  
        int _key;  
        ~Key();  
        /*重载<作为成员函数不行,两个操作数都要求是const*/  
        //bool operator <(const Key& key);  
    };  
    bool operator <(const Key &key1,const Key &key2)  
    {  
        if(key1._key<key2._key)  
            return true;  
        else  
            return false;  
    }  
    Key::Key()  
    {  
    }  
    Key::Key(int v)  
    {  
        _key=v;  
    }  
    Key::~Key()  
    {  
    }  
      
    void main()  
    {  
          
        map<Key,int> ClassMap;  
        Key one(1);  
        ClassMap.insert(make_pair(one,1));  
        Key two(2);  
        ClassMap.insert(make_pair(two,2));  
        Key three(3);  
        ClassMap.insert(make_pair(three,3));  
        map<Key,int>::iterator itor=ClassMap.begin();  
        while(itor!=ClassMap.end())  
        {  
            cout<<itor->first._key<<" ~~ "<<itor->second<<endl;  
            ++itor;  
        }  
    }  


 以上内容是转载 http://blog.csdn.net/xie376450483/archive/2011/04/17/6329408.aspx



纠正上例中的一个错误,重载<的时候,也可以这么做:

#include <map>  
    #include <iostream>  
    using namespace std;  
      
    class Key  
    {  
    public:  
        Key();  
        Key(int v);  
        int _key;  
        ~Key();  
       
        bool operator <(const Key& key) const;  
    };  
    bool Key::operator <(const Key &key)  const
    {  
        if(this->_key<key._key)  
            return true;  
        else  
            return false;  
    }  
    Key::Key()  
    {  
    }  
    Key::Key(int v)  
    {  
        _key=v;  
    }  
    Key::~Key()  
    {  
    }  
      
    void main()  
    {  
          
        map<Key,int> ClassMap;  
        Key one(1);  
        ClassMap.insert(make_pair(one,1));  
        Key two(2);  
        ClassMap.insert(make_pair(two,2));  
        Key three(3);  
        ClassMap.insert(make_pair(three,3));  
        map<Key,int>::iterator itor=ClassMap.begin();  
        while(itor!=ClassMap.end())  
        {  
            cout<<itor->first._key<<" ~~ "<<itor->second<<endl;  
            ++itor;  
        }  
    }  



  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Python中,我们可以通过自定义类来实现多关键字排序。 首先,我们可以在自定义类的构造函数中设置需要排序的关键字。假设我们需要按照学生的年龄(age)和成绩(score)两个关键字进行排序,我们可以这样定义一个Student类: ```python class Student: def __init__(self, name, age, score): self.name = name self.age = age self.score = score ``` 接下来,我们可以使用内置的`sorted()`函数来进行排序。为了实现多关键字排序,我们可以使用`key`参数传入一个函数,该函数可以根据我们的需求来定义排序的规则。 例如,如果我们想要按照年龄升序、成绩降序的方式对学生列表进行排序,可以定义一个排序函数: ```python def sort_key(student): return (student.age, -student.score) ``` 接下来,我们可以使用`sorted()`函数进行排序: ```python students = [ Student("Tom", 20, 80), Student("Alice", 18, 90), Student("Bob", 20, 70) ] sorted_students = sorted(students, key=sort_key) ``` 执行后,`sorted_students`列表将按照我们定义的排序规则进行排序。 在这个例子中,`sort_key`函数返回一个元组,元组中的第一个元素是年龄,第二个元素是成绩的负值。这样可以保证年龄相同时,按照成绩的降序进行排序。 以上便是使用自定义类实现多关键字排序的方法。通过定义排序函数,我们可以根据需要对多个关键字进行排序操作。 ### 回答2: 在Python中,我们可以使用关键字排序来对自定义类进行排序。 首先,我们需要定义一个自定义类,该类可以包含多个属性(关键字)。假设我们的自定义类为Person,具有属性name、age和salary。 我们可以通过重写类的特殊方法__lt__(小于)、__eq__(等于)和__gt__(大于)来实现对类对象的排序。这些方法分别表示对象之间的小于、等于和大于的比较操作。在这些方法中,我们可以根据需要指定对象之间的比较条件。 以下是一个简单的示例代码: ```python class Person: def __init__(self, name, age, salary): self.name = name self.age = age self.salary = salary def __lt__(self, other): if self.name != other.name: return self.name < other.name if self.age != other.age: return self.age < other.age return self.salary < other.salary def __eq__(self, other): return self.name == other.name and self.age == other.age and self.salary == other.salary def __gt__(self, other): return not self.__lt__(other) and not self.__eq__(other) # 创建Person对象的列表 persons = [Person("张三", 25, 5000), Person("李四", 25, 6000), Person("王五", 30, 5000)] # 根据多个关键字进行排序 persons.sort() # 输出排序结果 for person in persons: print(person.name, person.age, person.salary) ``` 以上代码创建了一个Person类,其中定义了__lt__、__eq__和__gt__方法,用于实现对象之间的比较操作。然后,我们创建了一个Person对象的列表,并使用sort方法对其进行排序。最后,我们按照指定的关键字顺序输出排序结果。 这样,就可以使用关键字自定义类进行排序了。 ### 回答3: 在自定义类中,可以通过重写比较方法来实现多关键字排序。 首先,需要定义一个包含多个属性的类,每个属性都代表了一个关键字。然后,在该类中重写比较方法,使其按照指定的排序顺序进行比较。 例如,假设我们要定义一个Person类,包含姓名(name)、年龄(age)和身高(height)三个属性。我们可以按照姓名升序、年龄降序、身高降序的顺序来排序。 首先,我们定义Person类: ```java public class Person { private String name; private int age; private double height; // 构造方法、getter和setter方法省略 // 重写比较方法 public int compareTo(Person other) { // 按照姓名升序排序 int result = this.name.compareTo(other.name); if (result != 0) { return result; } // 按照年龄降序排序 result = other.age - this.age; if (result != 0) { return result; } // 按照身高降序排序 return (int) (other.height - this.height); } } ``` 接着,我们可以使用自定义类进行排序。例如,创建一个Person对象的列表,然后使用Collections.sort()方法进行排序: ```java List<Person> personList = new ArrayList<>(); personList.add(new Person("Tom", 25, 180)); personList.add(new Person("Jerry", 30, 170)); personList.add(new Person("Alice", 20, 160)); Collections.sort(personList); for (Person person : personList) { System.out.println(person.getName()); } ``` 以上代码会按照姓名升序、年龄降序、身高降序的顺序输出人员的姓名: ``` Alice Jerry Tom ``` 这样,我们就通过重写比较方法,在自定义类中实现了多关键字排序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值