在QMap或QHash中进行QSet

时间:2012-04-19 20:44:20

标签: c++ qt qt4 comparison qmap

我有QMap我希望QSet成为它的关键,我不能这样做,因为QSet无法比较。 例如:

QSet<int> intSet;
QMap<QSet<int>, char> charSet;

intSet.insert(1);
intSet.insert(2);
intSet.insert(3);

charSet.insert(intSet, '6');

有什么方法可以让它发挥作用吗?如果我从QSet继承并定义operator <我应该如何实现它?即:比较的逻辑应该是什么?

注意:我过分关注性能

4 个答案:

答案 0 :(得分:5)

您似乎知道如何使其工作:定义一个operator<(const QSet<int>&)函数(我不相信Qt要求您将QSet子类化以使其工作,我知道STL不会。)

显然,在无序集上实现比较器将很困难。我认为,这样做是为了让它在恒定的时间内运行是不可能的。您可以先尝试检查大小,然后将这两个内容作为列表进行排序和比较。

但广泛地说:不要这样做。这是一种虐待。当然,您可以使用某些东西来设置不是可变数据结构的密钥。集合中的整数空间是固定的还是小的(即总是在0-1024或其他范围内)?然后尝试存储在QByteArray中的位掩码。等...

答案 1 :(得分:1)

你可以制作像这样的哈希方法

uint qHash(const QSet<int>& set) {
  uint seed = 0;

  for(int x : set) {
     seed ^= qHash(x) + 0x9e1559a9 + (seed << 6) + (seed >> 2);
  }
  return seed;
}

然后你的QMap就像这样

QMap<uint, char> charSet;

其中uint是先前方法的结果。

实际上这种方式不稳定100%,这取决于你的哈希函数。

答案 2 :(得分:0)

假设你并不担心性能(如果你使用容器作为关键,我认为这是一个公平的假设),那么我会做这样的事情。

QSet<int> intSet;
intSet << 1 << 2 << 3 << 3 << 4;

QVector<int> intVector;
intVector.reserve(intSet.size());
qCopy(intSet.begin(), intSet.end(), std::back_inserter(intVector)); // QVector doesn't have a std::vector range constructor atm
qSort(intVector);

QHash<QVector<int>, char> charHash;
charHash[intVector] = '6';

添加速度非常慢,但查找应该(相对)快。

我建议你想出一个更好的钥匙。也许是一个具有固定数量的int的简单类,您只需定义必要的运算符即可将其放入map / hash中。

答案 3 :(得分:0)

您似乎不需要值语义。禾为什么不用:

QHash<QSet<int> *, char> charSet;
//then to insert a set
charSet.insert(& intSet, '6');

但是对于每个集合,只有一个字符与集合对应,那么为什么不扩展QSet并添加其他成员?