如何对包含整数和对的以下映射进行排序?

时间:2015-07-01 21:12:40

标签: c++

所以,我有以下代码:

#include <iostream>
#include <unordered_map>
#include <utility>
#include <map>
using namespace std;

struct cmp 
{
    bool operator() (const pair<int,int>&a, const pair<int,int>&b)
    {
        if (a.first == b.first)
            return a.second<b.second;
        else
            return a.first > b.first;
    }
};
int main (void)
{
    int i=0,n,foo;
    cin>>n;
    map <int, pair<int,int>, cmp > mymap;
    while (i != n)
    {
        //auto it = mymap.begin();
        cin>>foo;
        if (mymap.find(foo) == mymap.end())
        {
            mymap[foo].make_pair(1,i);
        }
        else
        {
            mymap[foo].first++; 
        }
        i++;
    }
    auto it = mymap.begin();
    while (it != mymap.end())
    {
        cout<<it->first<<"\t"<<it->second.first<<"\t"<<it->second.second;
        cout<<"\n";
    }
    return 0;

}

此代码的作用基本上是采用输入元素并按频率对其进行排序(按递减顺序)。如果两个元素的频率相同,则输出首先出现在输入列表中的元素。

For ex: I/P: 2 5 2 8 5 6 8 8 
O/P: 8 8 8 2 2 5 5 6

我怀疑两个地方。首先,在我写的比较器函数中,它似乎是正确的,但它在编译时出错,

no matching function for call to object of type 'const cmp'
        {return static_cast<const _Hash&>(*this)(__x);}

另外,我用来打印输出的循环是正确的,尤其是it->second.first

2 个答案:

答案 0 :(得分:1)

cppreference.com开始,std::unordered_map定义为

template<

    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;

由于此容器是无序的,因此不需要比较器来对元素进行排序。

因此,将您的(无序)地图定义为

    unordered_map <int, pair<int,int> > mymap;

即。没有cmp

另外,不要忘记在上一个while循环中增加迭代器,即添加++it,否则 ...

您的示例现在应该编译:

$ ./mwe 
4
3
2
1
5
5   1   3
1   1   2
2   1   1
3   1   0

<强>更新

如果您将mymap的类型从std::unordered_map更改为,请参阅您的评论 std::map,请记住,元素将按其键排序。这不应该改变。 如果要按值对元素进行排序,请考虑以下替代方法:

使用std::vector,添加包含上述键和值的结构,并相应地更新cmp,例如

#include <algorithm>
#include <vector>
#include <tuple>

typedef std::tuple< int /* key */, int /* pair::first */, int /* pair::second */ > Element;
typedef std::vector< Element > ElementList;

template <int N>
bool cmp( const Element & a, const Element & b )
{
    return std::get< N >( a ) < std::get< N >( b );
}

int main()
{
    ElementList list;

    // Just dummy data, but you get the idea.
    list.push_back( std::make_tuple( 1, 2, 3 ) );
    list.push_back( std::make_tuple( 2, 3, 4 ) );
    list.push_back( std::make_tuple( 3, 4, 5 ) );

    // Sort by "pair::first", which is at element index 1 of 
    // the tuple, cf. cmp<1> below. Change this template parameter 
    // to the index value of the tuple element that should be used to 
    // sort your data.
    std::sort( list.begin(), list.end(), cmp<1> );

    return 0;
}

答案 1 :(得分:0)

map按其键排序,而不是按其值排序。请考虑使用set代替。