📜  按C++ STL中的值对地图排序(1)

📅  最后修改于: 2023-12-03 14:54:39.330000             🧑  作者: Mango

按C++ STL中的值对地图排序

在C++ STL中,可以使用map容器来存储键值对。通常情况下,我们按照键(key)进行排序。但是,有时我们需要根据值(value)来排序。

实现原理

map底层使用红黑树实现,红黑树是一种自平衡的二叉搜索树,具有以下特征:

  • 每个节点要么是红色,要么是黑色
  • 根节点和叶子节点(NULL)是黑色
  • 如果一个节点是红色,则它的子节点必须是黑色
  • 从任意节点到其每个叶子节点的所有路径必须包含相同数目的黑色节点
  • 具有以上性质的红黑树称为红黑树

由此可知,map底层使用的红黑树是可以自动排序的,因为红黑树是一颗二叉搜索树,具有左小右大的特点。

按值排序

但如果我们要按照值来排序呢?有一种简单粗暴的方法,先将map转换成向量(vector),再使用sort函数排序,最后再将排好序的向量转换回map

#include <iostream>
#include <map>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    map<int, string> m{{1, "one"}, {7, "seven"}, {3, "three"}, {9, "nine"}, {5, "five"}};
    vector<pair<int, string>> vec(m.begin(), m.end());
    sort(vec.begin(), vec.end(), [](const pair<int, string>& a, const pair<int, string>& b) -> bool {
        return a.second < b.second;
    });
    map<int, string> sorted_map(vec.begin(), vec.end());
    for (const auto& p : sorted_map) {
        cout << p.first << ": " << p.second << endl;
    }
}

上面的代码先将map转换成了一个向量vec,然后使用sort函数排序。注意,sort函数后面的第三个参数是一个lambda表达式,表示按照pair中的second进行排序(pair中的第一个元素为int型键,第二个元素为string型值)。最后,我们又将排好序的向量vec再次转换回了map

按值排序(C++17及以上)

如果你使用的是C++17或以上的版本,还可以使用std::map的新函数std::map::extractstd::map::insert来实现按值排序。

#include <iostream>
#include <map>

using namespace std;

int main() {
    map<int, string> m{{1, "one"}, {7, "seven"}, {3, "three"}, {9, "nine"}, {5, "five"}};
    map<string, int> sorted_map;
    for (auto& p : m) {
        sorted_map.insert(std::move(m.extract(p.first).value()));
    }
    for (const auto& p : sorted_map) {
        cout << p.second << ": " << p.first << endl;
    }
}

上面的代码先创建了一个空的std::map容器sorted_map,然后使用了m.extract(p.first)函数把每个键值对从原始的m容器中移动到了sorted_map容器中,这里的关键在于std::move的使用,它转移了键值对,而非复制。注意,extract函数多次调用后,原始的m容器已经变成一个空的容器。

总结

通过以上两种方式,我们可以很容易地实现对map容器按值排序的功能。如果你使用的是C++17及以上的版本,推荐使用第二种方式,因为它更加高效。