std :: map with std :: pair keys其中pair元素没有顺序重要性

时间:2013-03-14 21:00:43

标签: c++ stl

正如问题所说,我需要以这样的方式使用std :: map。

std::map<std::pair<int, int>, int*> m;

int* a_ptr = new int;
*a_ptr = 15;
m[std::make_pair(1, 2)] = a_ptr;
std::cout << *m[std::make_pair(2, 1)] << std::endl; //should output 15

现在,在我的实际实现中,所有键和值实际上都是指针。我该如何处理这个问题?

我想到了两个想法。

  1. 一个是我每次使用m[]时都应该写一个函数 访问或写入地图,我还应m.find()检查 其他一对组合并按此行事。

  2. 其他使用std :: unordered_map和自定义哈希 当pair的元素位置被切换时,以某种方式没有区别。 (我不知道怎么做,如果我乘以或添加 两个指针结果不一样。如果是这样,需要一些帮助 要走的路。)

  3. 如果你能想出一个更好的方法,我会很高兴听到它,否则我已经在第二个条款中陈述了我需要帮助的内容。 (我觉得效率更高,第一个看起来不太好)

    感谢。

4 个答案:

答案 0 :(得分:6)

你能简单地确保这些对总是处于相同的顺序吗?使用辅助函数,如:

std::pair<int,int> my_make_pair(int a, int b) 
{
    if ( a < b ) return std::pair<int,int>(a,b);
    else return std::pair<int,int>(b,a);
}

并始终使用它来访问地图:

m[my_make_pair(1,2)] = a_ptr;
std::cout << m[my_make_pair(2, 1)] << std::endl;

答案 1 :(得分:3)

template<typename T, typename PairCmp = std::less<std::pair<T,T>> >
struct symmetric_pair_sort {
  bool operator()( std::pair<T,T> const& left, std::pair<T,T> const& right ) const {
    if (left.second<left.first) {
      return (*this)(std::make_pair( left.second, left.first ), right );
    }
    if (right.second<right.first) {
      return (*this)(left, std::make_pair( right.second, right.first ) );
    }
    return PairCmp()(left, right);
  }
};

// or, the far bulkier yet more efficient:
template<typename T, typename PairCmp = std::less<std::pair<T&, T&>> >
struct symmetric_pair_sort {
  template<bool left_reversed, bool right_reversed>
  bool Helper( std::pair<T,T> const& left, std::pair<T,T> const& right ) const {
    std::pair<T&, T&> left_ordered( left_reversed?left.first:left.second, left_reversed?left.second:left.first );
    std::pair<T&, T&> right_ordered( right_reversed?right.first:right.second, right_reversed?right.second:right.first );
    return PairCmp()( left_ordered, right_ordered );
  }
  bool operator()( std::pair<T,T> const& left, std::pair<T,T> const& right ) const {
    if (left.second<left.first) {
      if (right.second<right.first) {
        return Helper<true, true>(left, right);
      } else {
        return Helper<true, false>(left, right);
      }
    } else {
      if (right.second<right.first) {
        return Helper<false, true>(left, right);
      } else {
        return Helper<false, false>(left, right);
      }
  }
};

std::map<std::pair<int, int>, int*, symmetric_pair_sort<int> > m;

答案 2 :(得分:3)

只需使用自定义比较器

[](std::pair<int, int> const& lhs, std::pair<int, int> const& rhs) {
   int lhs_min = std::min(lhs.first, lhs.second);
   int lhs_max = std::max(lhs.first, lhs.second);
   int rhs_min = std::min(rhs.first, rhs.second);
   int rhs_max = std::max(rhs.first, rhs.second);

   return lhs_min < rhs_min || (!(rhs_min < lhs_min) && lhs_max < rhs_max)
}

这是如何工作的?

前几行确定性地排序一对中的2个元素;也就是说,您可以按任意顺序提供它们lhs_min&amp; lhs_max将是相同的。然后,我们使用标准等效技术来得到结果。所有整数副本都将由编译器优化,min / max将被内联。

请注意,为了方便输入,我使用了C ++ 11的lambdas,并且发现没有很好的方法将它们用作std::map的比较器,所以你必须编写一个正确的函数。

答案 3 :(得分:1)

另一种解决方案是使用std::set<int>代替std::pair<int,int>。设置存储他们订购的数据,因此无需订购您的数据,因此精确满足您的要求。

另一方面,使用比较包装的其他答案明确地命令对可能更实用。