【问题标题】:Is there a fastest way to count object repetitions in an array than a HashTable?有没有比哈希表更快的方法来计算数组中的对象重复?
【发布时间】:2011-02-10 11:37:42
【问题描述】:

我会尽量说清楚。我已经实现了我的解决方案并且它有效,我只需要知道是否最好使用其他数据结构而不是哈希表

这是一个大学问题,但我已经提交给老师并且它有效,我只是想看看是否有人会做不同的事情。

所以,这就是问题所在:

给定图像(PPM 3,所有数据以 ASCII 格式存储在 RGB 中) 例如

P3
# The P3 means colors are in ASCII, then 3 columns and 2 rows,
# then 255 for max color, then RGB triplets
3 2
255
255   0   0     0 255   0     0   0 255
255 255   0   255 255 255     0   0   0

我需要将每个像素除以一个常数,即 2 的幂 (2,4,8…………64,128)

c= 32;
Pixel2(255/c,255/c,255/c) = Pixel2(7,7,7)

然后,我需要将所有像素转换为给定宽度的补丁,补丁将累积它包含的像素的RGB值

例如

w=3;   imageW = 10; imageH=10;
Patch[0].r = Pixel[0].r + Pixel[1].r + Pixel[2].r +
             Pixel[10].r + Pixel[11].r + Pixel[12].r +
             Pixel[20].r + Pixel[21].r + Pixel[22].r;
Patch[0].g = Same for g component;
Patch[0].b = Same for b component;

Patch[1].r = Pixel[1].r + Pixel[2].r + Pixel[3].r +
             Pixel[11].r + Pixel[12].r + Pixel[13].r +
             Pixel[21].r + Pixel[22].r + Pixel[23].r;
etc…

然后,我需要计算图像中每个补丁的重复次数。 所以,我所做的是我有一个 Image 类,它从文件(ifstream)中读取图像,还有一个 Pixel 类,它具有 r、g、b 和 nAparations 组件。我读取像素,将它们除以给定的常数,然后得到累积像素值的补丁。

在此之后,我们的 Image 类中有一个数据向量,它是一个补丁对象数组 例如

data = [Patch0{r comp,g comp, b comp, 1 parition}, Patch1{r comp,g comp, b comp, 1 parition} …..];

现在,我所做的是使用哈希表,插入每个补丁,如果它已经插入,只需更新它的 nAppearances 组件,如果没有,插入它。 全部插入后,返回一个包含哈希表中所有元素的向量。 这个向量,每个补丁只会出现一次,它的 nAppearances 组件将包含每个补丁在图像中出现的次数。

还有其他方法吗?还是哈希表是最好的方法?

另外,你会使用什么样的哈希函数?目前我正在使用

hash = patch.r * 1 + patch.g *2 + patch.b*3;
tableSize = maximun number of patches (assuming no one repeats)
insert into table[hash%tableSize];

哈希表允许冲突,表中的每个位置都有一个元素列表。

对不起,如果它太大了,只是想清楚一点。如果我的英语不够好也很抱歉! 谢谢。

【问题讨论】:

  • 嗯,我是这个课题的讲者之一,也是这个学生参加的编程大赛的组织者。随意帮助他,但假设学生必须自己解决比赛,或者只是阅读不同的编程资源而不使用对社区的主动查询。无论如何,当我检测到这个查询时,任何其他参与者都可以,并且完全禁止复制............

标签: c++ optimization hashtable repeat


【解决方案1】:

两件事

首先:如果你要散列颜色:

如果 R、G 和 B 是从 00 到 FF 的颜色,最简单的方法是创建一个 24 位的散列函数,即 RRGGBB,然后将其修改为一些素数,即散列表的大小。你的哈希表有多大?是素数吗?

例如 65536 将是一个非常糟糕的哈希表大小选择。 65539就好了。

unsigned int colornum(unsigned int red, unsigned int green, unsigned int blue) { 返回(红色

那么哈希就是colornum(r,g,b) % hashTableSize;

哈希的替代方案: 将 std::set 与 RGB 24 位数字一起使用,或与 rgb 数字一起使用,但使用 24 位数字进行比较。这样你就可以计算重复的数量。虽然它不如哈希快。

顺便说一句,如果你能负担得起,2^24 只有 16M,如果你使用的 bitset 将使用 2MB。您可以遍历所有颜色,为出现的每种颜色设置“标志”,然后以这种方式计算重复项。

【讨论】:

  • 您好,感谢您的回答。问题是它必须处理一组相当大的图像(我们不知道实际数量)和不同尺寸的图像(15x15、..、120x120、..、1024x1024..)。您对哈希函数的方法是我的想法,但我不知道如何实现它(主要是因为我没有想到逻辑 OR 函数......)。有不同大小的图像,我没有使用固定 tableSize,而不是每个图像可能的最大补丁数。如我所见,那么使用高素数会更好吗? (略低于 2 的幂)。
  • 好吧,经过一些测试,当插入 100 万个键(补丁)时,实现该哈希函数会导致哈希表快 30 倍。哇,真的。我一直在寻找,有很多“著名的快速”哈希函数(MurmurHash、FNV、SuperFastHash、谷歌的 Dense-hash ......)我可能会尝试,尽管它们对于字符串键似乎更快。
【解决方案2】:

使用@CashCow 哈希函数我获得了相当快的速度。

unsigned int colornum(unsigned int red, unsigned int green, unsigned int blue) { return (red

那么 hash 就是 colornum(r,g,b) % hashTableSize;

问题是,我需要计算大量图像的补丁重复次数(一次一个),并且它们可以变化很大(一个可能只有 81 个补丁,10x10图像,其他可能是 1024x1024,如果全部不同,则最多可添加 +100 万个补丁。)

所以我在为每个图像中的此操作( colornum(r,g,b) % hashTableSize) 调整 hashTableSize 时遇到问题,因为对于非常小的图像来说大数字不是最佳的,相反会导致很多碰撞...... 我还研究了其他著名的快速哈希函数,例如 murmurhash2,但我不知道如何正确实现它们。 (我还需要对它们返回的 unsigned int 执行 % hashtableSize 吗?因为如果是,那么我认为它们不应该比 @CashCow 建议更快,因为我做的操作要少得多)

如果有任何迹象,就在这之后,我需要检索补丁数组并对其进行排序(因为我需要比较它们并找到差异,据我所知,这是最快的方法比较两个对象数组首先让它们排序对吗??)所以如果你知道任何可以快速计算重复次数的方法,并且让我稍后检索它已经排序的说出来。

我认为平衡树可能会解决问题,查找和插入都是渐近最差的,但是对于完全不同大小的图像,我会摆脱这个问题,而且我可以检索它们排序通过 trasversal Inorder(不知道这就是它的英文名称..)。 对此的任何想法将不胜感激。再次感谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 2020-08-12
    相关资源
    最近更新 更多