C++ 以vualue排序一个map

2015-03-29 Mithrilwoodrat 更多博文 » 博客 » GitHub »

原文链接 http://woodrat.xyz/2015/03/29/c-%e4%bb%a5vualue%e6%8e%92%e5%ba%8f%e4%b8%80%e4%b8%aamap/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


为了找工作重新拾起 C++.才发现,被 Python 宠坏后,再回头使用 c++,一下子无法适应如此复杂的情况.

回到正题,C++ 中如何排序一个 map.

我们都知道无法使用 std::sort 来排序 map,只有通过间接的方法.参考 stackoverflow 上的几个答案.

我们假设输入为一组数字,输出为数字和其出现次数,以出现次数从大到小排序,若出现次数相同,则数字小的先输出.

样例输入为 1 2 3 3 4 5 5 2
以下代码均来自(或改自) stackoverflow.

第一种方法为将map中的key和value对换,装入multimap中,multimap输出时有序.

#include <map>

include <algorithm>

include <iostream>

template<typename A, typename B> std::pair<B, A> flip_pair(const std::pair<A, B> &p) { return std::pair<B, A>(p.second, p.first); }

template<typename A, typename B> std::multimap<B, A> flip_map(const std::map<A, B> &src) { std::multimap<B, A> dst; std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), flip_pair<A, B>); return dst; }

int main (void) { std::map<int, int> num_count; std::map<int, int>::iterator map_it; int num; while(std::cin >> num) num_count[num]++;

for (const auto & n : num_count)
    std::cout &lt;&lt; n.first &lt;&lt;  :  &lt;&lt; n.second &lt;&lt; std::endl;

std::cout &lt;&lt; std::endl;

std::multimap&lt;int, int&gt; dst_map = flip_map(num_count);
for (const auto & n : dst_map)
    std::cout &lt;&lt; n.second &lt;&lt;  :  &lt;&lt; n.first &lt;&lt; std::endl;
    return 0;

}

此时输出为

1 : 1 4 : 1 5 : 2 2 : 2 3 : 2

虽然是按出现次数排序,但并未满足第二条件.

要想使用自定义的比较方法排序,一种方法为将map输入到一个vector中,在自定义cmp方法,使用algorith库中sort方法来排序

#include <map>

include <algorithm>

include <iostream>

include <vector>

int main (void) { std::map<int, int> num_count; std::map<int, int>::iterator map_it; int num; while(std::cin >> num) num_count[num]++; std::vector<std::pair<int, int> > dst_vec; std::copy(num_count.begin(), num_count.end(), std::back_inserter(dst_vec)); auto cmp = { return a.second != b.second ? a.second > b.second : a.first < b.first; };

std::sort(dst_vec.begin(),dst_vec.end(), cmp);

for(const auto & n : dst_vec)
    std::cout &lt;&lt; n.first &lt;&lt;  :  &lt;&lt; n.second &lt;&lt; std::endl;
return 0;

}

此时输出为

2 : 2 3 : 2 5 : 2 1 : 1 4 : 1

满足条件