稳定排序C ++哈希映射 - 保留相等元素

时间:2018-03-10 19:58:47

标签: c++ sorting data-structures hashmap

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

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

就我而言,只要时间可以改善,空间就不是问题。我想利用它并做一个桶分类。哪个应该给我O(N)时间复杂度。但是当使用桶排序时,没有编译器,当迭代地图中的项时,订单不会被保留。

如何通过铲斗分类或其他方式使其稳定并仍保持O(N)时间复杂度? 我想如果我有一些哈希映射在迭代时保留插入顺序,它将解决我的问题。

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

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

1 个答案:

答案 0 :(得分:0)

以下是我使用std::unordered_map提出的可能解决方案,并使用std::vector跟踪插入顺序。

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

        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);