【问题标题】:C++ map using pair as key使用对作为键的 C++ 映射
【发布时间】:2013-02-25 03:18:56
【问题描述】:

我正在使用映射(这似乎是previous question 之后最好的实现,带有一对键,作为传入消息的“容器”,可以根据 sourceID 和优先级进行排序,即键:(sourceID,优先级)它指向一个 int 值。 处理将在此地图“上”进行。

我刚刚遇到一个问题 - 我需要执行类似以下伪代码的操作来随后检索消息:

map<pair<int, int>, int> mymap;

if (!mymap[make_pair(nodeID,i)].empty()) //i refers to all the priority levels
    //processing occurs here to retrieve a value

但我似乎不能轻易做到。有没有办法在不运行迭代器的情况下简单地做到这一点,例如for (i = 0; i &lt;priority ; i++)?我知道,如果我使用等效的 vector&lt;vector&lt;int&gt;&gt;,我将能够轻松地做到这一点,但目前地图更适合我的程序。

编辑:

消息按(sourceID,优先级)排序到映射中,然后在按(destID,优先级)映射到另一个映射之前进行处理。我需要检查是否有可用于任何特定 destID 的消息,无论优先级如何,因此我正在寻找一种简单的方法来检查这一点。

我知道,如果我使用vector&lt;vector&lt;int&gt;&gt;,如果我想检查节点 2 是否没有可用消息,我将能够执行node[2].empty() 之类的操作。有地图的等价物吗?

【问题讨论】:

  • 嗯?你的伪代码对我没有意义。 mymap[make_pair(nodeID,i)]int,你不能在上面调用 empty()。你能更清楚地描述你想要做什么吗?
  • 你为什么要重新发布你的问题?
  • 问题不同了,我现在编辑一下更清楚。
  • 你需要mymap.find(make_pair(nodeID,i)) != mymap.end()

标签: c++ dictionary containers std-pair


【解决方案1】:

如果我的理解正确,您需要一种方便的方法来确定地图有多少条目(node_id,i),其中node_id 是固定的,i 可以是任何东西。

如果这个理解是正确的,你可以利用 map 中的排序是基于 std::less&lt;std::pair&lt;int,int&gt;&gt; 定义的排序,默认情况下是字典顺序。换句话说,node-id 将作为主要的排序标准,而对中的第二个元素将作为次要的排序标准。

因此,您可以使用映射的 lower_boundupper_bound 函数来确定给定节点 ID 的条目范围,如下所示(C++11 代码,但可以转换为 C++03) :

std::ptrdiff_t num_per_node(const mymap &map, const int node_id)
{
  using std::distance;
  static constexpr int min = std::numeric_limits<int>::min();
  static constexpr int max = std::numeric_limits<int>::max();

  auto lo = map.lower_bound({node_id,min});
  auto hi = map.upper_bound({node_id,max});
  return distance(lo,hi);
}

上面定义的函数返回给定节点 ID node_id 的映射 map 中的条目数。

所以你的伪代码变成了:

if (num_per_node(mymap,nodeID) > 0)

该函数具有对数复杂度,这显然(渐近地)优于遍历所有优先级值。

请注意,这只有效,因为您的对的元素是int,因此很容易建立最小值和最大值。同样,它也仅因字典顺序而起作用。如果您在地图上使用自定义的比较器功能,则此方法将不再有效,是否可以找到对应的方法取决于您的比较器是如何定义的。

这是一个 GIT-gist,其中包含一个完整的示例,演示了如何使用该函数:https://gist.github.com/jogojapan/5027365

【讨论】:

    【解决方案2】:

    只是在 @jogojapan 所做的工作的基础上,我已经对其进行了调整,使其不使用 C++11(因为我没有使用它),并将其留在这里以供参考。不确定它会做他做的所有事情,但对我来说足够用

    #include <iostream>
    #include <utility>
    #include <limits>
    #include <map>
    
    using namespace std;
    
    std::ptrdiff_t num_per_node(const map<pair<int, int>, int> &map, const int node_id)
    {
      using std::distance;
      static int min = std::numeric_limits<int>::min();
      static int max = std::numeric_limits<int>::max();
    
        auto lo = map.lower_bound(make_pair(node_id,min));
        auto hi = map.upper_bound(make_pair(node_id,max));
        return distance(lo,hi);
      }
    
      int main() {
        map<pair<int, int>, int> m;
        m.insert(make_pair(make_pair(1,3),1));
        m.insert(make_pair(make_pair(3,4),2));
        m.insert(make_pair(make_pair(3,5),3));
        m.insert(make_pair(make_pair(3,9),4)); 
        m.insert(make_pair(make_pair(4,2),5)); 
        m.insert(make_pair(make_pair(4,3),6)); 
        m.insert(make_pair(make_pair(5,1),7)); 
        m.insert(make_pair(make_pair(8,2),8));
    
        for (int node_id = 0 ; node_id < 10 ; ++node_id)
          std::cout << "node-id " << node_id << ": " << num_per_node(m,node_id) << '\n';
    
        return 0;
      }
    

    正确返回

    node-id 0: 0
    node-id 1: 1
    node-id 2: 0
    node-id 3: 3
    node-id 4: 2
    node-id 5: 1
    node-id 6: 0
    node-id 7: 0
    node-id 8: 1
    node-id 9: 0
    

    【讨论】:

    • 为您的努力+1。实际上,您一定在某个地方使用了 C++11,因为它显然接受了我们对 auto 的使用,这严格来说是 C++11。这是一个完整的 C++03 版本,带有 typedefs 而不是我的 using-aliases:liveworkspace.org/code/4xo1cJ$2
    • 我想我的是你的婴儿床,@jogojapan(对此完全陌生)。我只是试图纠正 vbcpp2010 中红色下划线的内容。我似乎无法访问您的链接!
    • This link 希望是正确的。这要么是 Markdown 格式问题,要么是我的复制/粘贴错误。
    【解决方案3】:

    一种可能的解决方案是使用 2 个嵌套地图:

    typedef std::map<int,int> priorities;
    typedef std::map<int,priorities> messages;
    

    查找给定 sourceId 是否有任何消息,并且当您需要查找具有给定 sopurceId 和优先级的消息时,任何优先级对于 2 次查找的价格来说都是微不足道的。

    【讨论】:

      猜你喜欢
      • 2011-03-17
      • 2016-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-02
      • 2012-01-23
      • 2015-10-20
      相关资源
      最近更新 更多