【问题标题】:QSet in QMap or QHashQMap 或 QHash 中的 QSet
【发布时间】:2014-03-14 18:46:20
【问题描述】:

我有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 &lt; 我应该如何实现它?即:比较的逻辑应该是什么?

注意:我太在乎性能了

【问题讨论】:

标签: c++ qt qt4 comparison qmap


【解决方案1】:

您似乎知道如何使它工作:定义一个operator&lt;(const QSet&lt;int&gt;&amp;) 函数(我不相信Qt 要求您将QSet 子类化才能使其工作,我知道STL 不需要)。

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

但概括地说:不要这样做。这是一种虐待。当然,您可以将某些东西用作集合的键,而不是可变数据结构。集合中的整数空间是否固定且很小(即始终在 0-1024 或其他范围内)?然后尝试存储在 QByteArray 中的位掩码。等等……

【讨论】:

    【解决方案2】:

    你可以做一个这样的哈希方法

    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% ,这取决于你的哈希函数。

    【讨论】:

    • 如果你定义了qHash函数,那么你可以直接在QHash中使用散列结构,也就是你可以写QHash&lt;QSet&lt;int&gt;, char&gt;
    • 我将 qHash 用于集合内的元素,其中 qHash 未定义为所有集合
    • 但正如我所见,您已经使用预定义的qHash(int) 为整个QSet&lt;int&gt; 定义了qHash。顺便说一句,为什么要将 0x9e1559a9 添加到 seed 并转移 &lt;&lt; 6&gt;&gt;2
    • 上述哈希函数不起作用。 不要使用它。参照。 stackoverflow.com/questions/9126470/… 为正确的qHash(QSet)
    【解决方案3】:

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

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

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

    【讨论】:

    • 尽管这些语义不兼容(当然,它们是否符合 OP 的要求是一个悬而未决的问题)。这个问题要求一个容器来处理例如。所有空集都相等并且只存储一个值。存储指针将为插入的每个不同的空集存储一个值。
    • @AndyRoss 如果作者询问如何实现集合比较的想法,那么我怀疑他需要这种比较。集合比较可以通过多种方式实现。
    【解决方案4】:

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

    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 中。

    【讨论】:

    • 我很担心性能,我认为它对我不起作用:(
    • 然后专注于制作一个生成速度非常快的密钥。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多