【问题标题】:Call order refer to some information调用顺序参考一些信息
【发布时间】:2011-04-06 20:05:19
【问题描述】:

现在我有std::map<std::string, Object> myMapObject 类具有函数:int getPriority()void Work()。现在我浏览地图,由于对象的优先级,我想打电话给Work

我写了一个非常疯狂的想法:那个地图的克隆,但是它存储在它的优先级的键中,例如:

myMap["3_key1"] = Object();
myMap["6_key2"] = Object();
myMap["0_key3"] = Object();

它排序并且调用在正确的队列中:0_key3; 3_key1; 6_key2

但我认为这很慢。我想用 boost 中的unordered_map 替换std::map,因为它要快得多。而且没有按键排序。

那么,有什么想法吗?

【问题讨论】:

  • 我能问一下为什么你认为它很慢吗?
  • 另外,你知道unordered_map的哪些操作比标准的map更快吗?
  • @GMan 是的。 @kiril-kirov 简单插入。

标签: c++ sorting map queue call


【解决方案1】:

使用Boost.MultiIndex:

// your class
#include <iostream>
#include <string>

class foo
{
public:
    foo(std::string name, unsigned priority, std::string msg) :
    mPriority(priority)
    {
        mName.swap(name); // primitive std::move :)
        mMsg.swap(msg); // (default-construct & swap)
    }

    const std::string& name() const
    {
        return mName;
    }

    unsigned priority() const
    {
        return mPriority;
    }

    void work() const
    {
        std::cout << mMsg << std::endl;
    }

private:
    std::string mName;

    unsigned mPriority;
    std::string mMsg;
};

// your container
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>

namespace bmi = boost::multi_index;

typedef boost::multi_index_container<foo,
            bmi::indexed_by<
                // order by name (std::map)
                bmi::ordered_unique<
                    bmi::const_mem_fun<foo, const std::string&, &foo::name>
                        >,

                // order by priority (std::multi_map)
                bmi:: ordered_non_unique<
                    bmi::const_mem_fun<foo, unsigned ,&foo::priority>
                        >
                > 
            > foo_set;

// test
#include <boost/foreach.hpp>

int main()
{
    foo_set fooSet;
    fooSet.insert(foo("a", 4, "this is a, priority 4"));
    fooSet.insert(foo("b", 3, "this is b, priority 3"));
    fooSet.insert(foo("c", 7, "this is c, priority 7"));
    fooSet.insert(foo("d", 1, "this is c, priority 1"));

    // view as map from name to value
    foo_set::nth_index<0>::type& nameView = fooSet.get<0>();

    nameView.find("a")->work(); // find "a", print its message
    if (nameView.find("e") == nameView.end())
        std::cerr << "e not found" << std::endl;

    std::cout << std::endl;

    // view as multi_map from priority to value
    foo_set::nth_index<1>::type& priorityView = fooSet.get<1>();

    BOOST_FOREACH(const foo& f, priorityView)
        f.work(); // work, in order of priority
}

我没有对其进行任何性能测试,但它肯定能更好地表达您的意图,而且这通常表明性能有所提高。

【讨论】:

  • 很好的答案。但是,一如既往:)
【解决方案2】:

我认为最简单的方法是两个容器。您当前的键-> 值映射,以及按对象优先级排序的第二个键堆(可能只使用 priority_queue 作为您的堆实现)。不过,这将有优先级的困难可以随时更改。

【讨论】:

    【解决方案3】:

    如果你使用 std::set 或 std::priority_queue 而不是 std::map,你可以定义一个仿函数,或者简单地为你的类实现 operator

    #include <iostream>
    #include <set>
    
    class Object {
      public:
        int m_priority;
    
        Object(int p) : m_priority(p) { }
    
        int getPriority() const { return m_priority; }
    
        void Work() const { std::cout << m_priority << std::endl; }
    };
    
    bool operator<(const Object & lhs, const Object & rhs)
    {
        return lhs.getPriority() < rhs.getPriority();
    }
    
    int main()
    {
        std::set<Object> container;
    
        container.insert(Object(1));
        container.insert(Object(9));
        container.insert(Object(5));
        container.insert(Object(8));
        container.insert(Object(3));
    
        for (std::set<Object>::iterator I = container.begin();
             I != container.end();
             ++I) {
            I->Work();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 2021-05-16
      • 2021-10-11
      相关资源
      最近更新 更多