10

我想为一对无序的整数存储一个浮点值。我找不到任何易于理解的教程。例如对于无序对{i,j},我想存储一个浮点值f。如何插入、存储和检索这样的值?

4

3 回答 3

12

处理无序 int 对的简单方法是使用std::minmax(i,j)生成std::pair<int,int>. 这样你就可以像这样实现你的存储:

   std::map<std::pair<int,int>,float> storage;
   storage[std::minmax(i,j)] = 0.f;
   storage[std::minmax(j,i)] = 1.f; //rewrites storage[(i,j)]

诚然,正确的散列会给你一些额外的性能,但推迟这种优化几乎没有什么坏处。

于 2016-08-14T12:55:59.207 回答
1

您根据您的要求和重载实现类型 UPair ::std::hash(这是允许您在 中实现某些东西的罕见情况std)。

#include <utility>
#include <unordered_map>

template <typename T>
class UPair {
  private:
    ::std::pair<T,T> p;
  public:
    UPair(T a, T b) : p(::std::min(a,b),::std::max(a,b)) {
    }   
    UPair(::std::pair<T,T> pair) : p(::std::min(pair.first,pair.second),::std::max(pair.first,pair.second)) {
    }   
    friend bool operator==(UPair const& a, UPair const& b) {
      return a.p == b.p;
    }   
    operator ::std::pair<T,T>() const {
      return p;
    }   
};
namespace std {
  template <typename T>
  struct hash<UPair<T>> {
    ::std::size_t operator()(UPair<T> const& up) const {
      return ::std::hash<::std::size_t>()(
               ::std::hash<T>()(::std::pair<T,T>(up).first)
             ) ^
             ::std::hash<T>()(::std::pair<T,T>(up).second);
      // the double hash is there to avoid the likely scenario of having the same value in .first and .second, resulinting in always 0
      // that would be a problem for the unordered_map's performance
    }   
  };  
}

int main() {
  ::std::unordered_map<UPair<int>,float> um;
  um[UPair<int>(3,7)] = 3.14;
  um[UPair<int>(8,7)] = 2.71;
  return 10*um[::std::make_pair(7,3)]; // correctly returns 31
}
于 2015-03-24T16:39:43.950 回答
1

这是一些指示性代码:

#include <iostream>
#include <unordered_map>
#include <utility>

struct Hasher
{
    int operator()(const std::pair<int, int>& p) const
    {
        return p.first ^ (p.second << 7) ^ (p.second >> 3);
    }
};

int main()
{
    std::unordered_map<std::pair<int,int>, float, Hasher> m =
    { { {1,3}, 2.3 },
      { {2,3}, 4.234 },
      { {3,5}, -2 },
    };

    // do a lookup
    std::cout << m[std::make_pair(2,3)] << '\n';
    // add more data
    m[std::make_pair(65,73)] = 1.23;
    // output everything (unordered)
    for (auto& x : m)
        std::cout << x.first.first << ',' << x.first.second
            << ' ' << x.second << '\n';
}

请注意,它依赖于您首先存储具有较小数字的无序对(如果它们不相等)的约定。您可能会发现编写一个接受一对并按该顺序返回它的支持函数很方便,因此您可以在映射中插入新值以及使用对作为键以尝试在地图。

输出:

4.234
3,5 -2
1,3 2.3
65,73 1.23
2,3 4.234

ideone.com上查看。如果你想制作一个更好的散列函数,只需寻找hash_combine(或使用 boost's)的实现——这里有很多关于 SO 的问题解释如何为std::pair<>s 做到这一点。

于 2015-03-24T16:03:45.803 回答