使用pair作为键的C ++映射

时间:2013-02-25 03:18:57

标签: c++ dictionary containers std-pair

我正在使用地图(这似乎是previous question之后的最佳实现,带有一对密钥,作为传入消息的“容器”,可根据sourceID和优先级进行排序,即:key:(sourceID, priority)指向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 <priority ; i++)?我知道,如果我使用等效vector<vector<int>>我可以轻松地做到这一点,但目前地图对我的程序效果更好。

编辑:

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

我知道如果我使用vector<vector<int>>,我将能够执行类似node[2].empty()的操作,如果我想检查节点2没有可用的消息。是否有相应的地图?

3 个答案:

答案 0 :(得分:3)

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

如果这种理解是正确的,你可以利用这样一个事实,即地图内的排序是基于std::less<std::pair<int,int>>定义的排序,默认情况下是字典排序。换句话说,node-id将用作主要的排序标准,而该对的第二个元素将用作次要排序标准。

因此,您可以使用映射的lower_boundupper_bound函数来确定给定node-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);
}

上面定义的函数返回给定node-id map的地图node_id中的条目数。

所以你的伪代码变成了:

if (num_per_node(mymap,nodeID) > 0)

该函数具有对数复杂度,明显(渐近)比迭代所有优先级值更好。

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

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

答案 1 :(得分:1)

仅仅基于@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

答案 2 :(得分:0)

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

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

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