使用对向量作为unordered_map [已关闭]

Use a vector of pairs as an unordered_map [closed]

提问人:Sarcana 提问时间:7/22/2023 最后编辑:ks1322Sarcana 更新时间:7/22/2023 访问量:79

问:


想改进这个问题吗?通过编辑这篇文章来更新问题,使其仅关注一个问题。

4个月前关闭。

我最初使用unordered_map来存储某个数字出现的频率,然后使用priority_queue来实现最大堆,以获得出现次数最多的第一个元素。但是unordered_map没有保留插入顺序,我正在考虑为此使用对向量。

我之前尝试过实现这一点,但是由于vector<int,int>不是我需要使用的有效模板,因此我可以简单地计算频率。我怎样才能计算出其中元素的频率? 我尝试将find与一对向量一起使用,并尝试了和.如果这些似乎不起作用,我如何找到该元素并更改其频率值?unordered_map<int,int>mpmp[element]++vector<pair<int,int>> vecif(find(vec.begin().first,vec.end().first,node)==vec.end().first)if(find(vec.first.begin(),vec.first.end(),node)==vec.first.end())

C++ std 标准向量 stdmap

评论

0赞 Some programmer dude 7/22/2023
你的实际任务或练习是什么?请将其复制粘贴到您的问题中(完整且完整,包括所有要求和限制,并作为文本)。如果您直接询问,我们将能够更好地为您提供帮助。
0赞 Homer512 7/22/2023
一个重要的方面是,您是需要在每次插入/更新后找到最常见的元素,还是在计算所有条目后才找到最后
0赞 Miles Budnek 7/22/2023
您的密钥是否连续,它们的范围是否有限?如果是这样,您可以只使用并预先分配一个足够大的向量来容纳整个键范围(即,如果计算 ASCII 字符或类似字符的频率)。std::vector<int>
0赞 n. m. could be an AI 7/22/2023
为什么需要保持插入顺序?

答:

1赞 Vlad from Moscow 7/22/2023 #1

使用效率低下。使用会好得多.std::vectorstd::map

但是,如果要使用向量并且它是未排序的,那么您需要使用标准算法。std::find_if

这是一个演示程序,展示了如何做到这一点。

#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
#include <algorithm>

int main()
{
    std::vector<std::pair<int, int>> v;

    for (auto key : { 1, 2, 3, 4, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1 })
    {
        auto present = [=]( const auto &p ) { return p.first == key; };

        auto pos = std::find_if( std::begin( v ), std::end( v ), present );

        if (pos == std::end( v ))
        {
            v.emplace_back( key, 1 );
        }
        else
        {
            ++pos->second;
        }
    }

    for ( const auto &p : v )
    {
        std::cout << p.first << ": " << p.second << '\n';
    }

    return 0;
}

程序输出为

1: 2
2: 5
3: 4
4: 3
5: 1
0赞 fabian 7/22/2023 #2

您可能只想跟踪 in a 中的插入顺序。您可能需要为此编写一个包装器类型。std::unordered_mapstd::vector<std::unordered_map<...>::value_type*>


template<class Key, class Value>
class MyMap
{
    using Map = std::unordered_map<Key, Value>;
    using Entry = std::unordered_map<Key, Value>::value_type;
    using ConstEntry = std::add_const_t<Entry>;

    Map m_map;
    std::vector<typename Map::value_type*> m_insertionOrder;
public:
    auto& operator[](Key const& key)
    {
        auto insertResult = m_map.try_emplace(key);
        if (insertResult.second)
        {
            try
            {
                m_insertionOrder.push_back(&*insertResult.first);
            }
            catch (...)
            {
                m_map.erase(key);
                throw;
            }
        }

        return insertResult.first->second;
    }

    template<bool isConst>
    class IteratorImplementation
    {
        std::vector<typename Map::value_type*>::const_iterator m_pos;
    public:
        using value_type = std::conditional_t<isConst, ConstEntry, Entry>;
        using reference = value_type&;
        using difference_type = void;
        using pointer = value_type*;
        using iterator_category = std::forward_iterator_tag;

        IteratorImplementation(std::vector<typename Map::value_type*>::const_iterator pos) noexcept
            : m_pos(pos)
        {
        }
        
        bool operator==(IteratorImplementation const& other) const noexcept
        {
            return m_pos == other.m_pos;
        }
        
        bool operator!=(IteratorImplementation const& other) const noexcept
        {
            return m_pos != other.m_pos;
        }

        reference operator*() const
        {
            return **m_pos;
        }

        pointer operator->() const
        {
            return *m_pos;
        }

        IteratorImplementation& operator++()
        {
            ++m_pos;
            return *this;
        }

        IteratorImplementation operator++(int)
        {
            IteratorImplementation result = *this;
            ++(*this);
            return result;
        }
    };

    auto begin() const noexcept
    {
        return IteratorImplementation<true>(m_insertionOrder.begin());
    }

    auto end() const noexcept
    {
        return IteratorImplementation<true>(m_insertionOrder.end());
    }
};

int main()
{
    std::vector<int> values;

    for (int i = 0; i <= 25; ++i)
    {
        values.push_back(i);
    }

    for (int i = 25; i >= 0; i -= 2)
    {
        values.push_back(i);
    }

    MyMap<int, int> map;

    for (auto e : values)
    {
        ++map[e];
    }

    for (auto [key, value] : map)
    {
        std::cout << key << " -> " << value << '\n';
    }

    auto maxElement = std::max_element(map.begin(), map.end(), [](std::pair<const int, int> const& v1, std::pair<const int, int> const& v2)
        {
            return v1.second < v2.second;
        });

    std::cout << "max: " << maxElement->first << '\n';

}