【问题标题】:Stable sort a C++ hash map - preserve the insertion order for equal elements稳定排序 C++ 哈希映射 - 保留相等元素的插入顺序
【发布时间】:2018-08-19 04:29:27
【问题描述】:

假设我有一个std::unordered_map<std::string, int>,它代表一个单词以及该单词在书中出现的次数,我希望能够按值对其进行排序。
问题是,我希望排序是稳定的,这样如果两个项目具有相同的值,我希望首先插入到地图的项目是第一个。

通过添加添加字段来实现它很简单,该字段将保持插入的time。然后,创建一个同时使用timevalue 的比较器。使用简单的std::sort 会给我O(Nlog(N)) 时间复杂度。

就我而言,只要可以改进时间,空间就不是问题。我想利用它并进行桶排序。这应该给我O(N) 时间复杂度。但是当使用桶排序时,没有比较器,当迭代地图中的项目时,不会保留顺序。

如何通过桶排序或其他方式使其既稳定又保持 O(N) 时间复杂度?
我想如果我有某种哈希映射在迭代时保留插入顺序,它会解决我的问题。

任何其他具有相同时间复杂度的解决方案都是可以接受的。

注意 - 我已经看到 thisthat 并且由于它们都来自 2009 年并且我认为我的情况更具体,所以我提出了这个问题。

【问题讨论】:

  • 示例不可能正确。如何区分两个相等的字符串?即使它们是带有字符串键的更复杂的对象,我也看不出会有什么困难。
  • @JiveDadson 如果它们相等,我将增加计数器。也许我没有得到你的问题。

标签: c++ sorting data-structures hashmap


【解决方案1】:

这是我想出的一个可能的解决方案,我使用 std::unordered_map 并使用 std::vector 跟踪插入顺序。

  1. 创建一个以字符串为键、计数为值的哈希映射。
    此外,创建一个带有该映射类型的迭代器的向量。
  2. 计数元素时,如果对象尚未在地图中,则将其添加到地图和矢量中。否则,只需增加计数器。向量将保留元素插入到地图中的顺序,并且插入/更新的时间复杂度仍为O(1)
  3. 通过遍历向量(而不是映射)来应用桶排序,这样可以确保保留顺序并且我们将获得稳定的排序。 O(N)
  4. 从存储桶中提取以生成排序数组。 O(N)

实施:

    unordered_map<std::string, int> map;
    std::vector<std::unordered_map<std::string,int>::iterator> order;

    // Lets assume this is my string stream
    std::vector<std::string> words = {"a","b","a" ... };

    // Insert elements to map and the corresponding iterator to order
    for (auto& word : words){
        auto it = map.emplace(word,1);
        if (!it.second){
            it.first->second++;
        }
        else {
            order.push_back(it.first);
        }
        max_count = std::max(max_count,it.first->second);
    }

    //  Bucket Sorting
    /*  We are iterating over the vector and not the map
        this ensures we are iterating by the order they got inserted */
    std::vector<std::vector<std::string>> buckets(max_count);
    for (auto o : order){
        int count = o->second;
        buckets[count-1].push_back(o->first);
    }

    std::vector<std::string> res;
    for (auto it = buckets.rbegin(); it != buckets.rend(); ++it)
        for (auto& str : *it)
            res.push_back(str);

【讨论】:

    猜你喜欢
    • 2010-12-26
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 2014-02-01
    相关资源
    最近更新 更多