【发布时间】:2015-08-09 13:31:46
【问题描述】:
我需要存储一组元素。我需要的是功能
- 删除(单个)元素并
- 添加(组)元素和
- 每个对象只能在集合中出现一次并且
- 从集合中随机获取一个元素
我选择了 HashSet (C#),因为它采用 fast 方法来删除元素 (hashSet.remove(element)),添加集合 (hashSet.UnionWith (anotherHashSet)) 并且 HashSet 的性质保证不存在重复,因此需要注意要求 1 到 3。
我发现获得随机元素的唯一方法是
Object object = hashSet.ElementAt(rnd.Next(hashSet.Count));
但这非常慢,因为我为地图的每个像素调用一次(从多个起点创建随机洪水填充;目前地图大小为 500x500,但我想更大)并且哈希集相当很多项目。 (快速测试表明它在再次缩小之前会炸毁多达 5752 个条目。)
分析(CPU 采样)告诉我 ElementAt 调用占了 50% 以上。
我意识到对大哈希集进行 500x500 操作并非易事,但其他操作(Remove 和 UnionWith)的调用频率与 ElementAt 一样频繁,因此主要问题似乎是操作而不是调用次数。
我隐约明白为什么从 HashSet 中获取某个元素非常昂贵(与从列表或其他有序数据结构中获取它相比,但我只想随机选择。真的很难吗?有没有办法解决它?是否有更好的数据结构适合我的目的?
将所有内容更改为 Lists 并没有帮助,因为现在其他方法成为瓶颈,并且需要更长的时间。
将 HashSet 转换为一个数组并从中选择我的随机元素预计没有帮助,因为虽然从数组中选择一个随机元素很快,但首先将 hashset 转换为数组需要比运行 hashSet.ElementAt 更长的时间自己。
如果你想更好地理解我想要做什么:A link to my question and the answer.
【问题讨论】:
-
你要删除什么?它只是随机找到的元素,还是任意的?
-
为什么不使用 HashSet 进行所有添加和删除操作,然后在进行随机像素获取之前,只需转换为 List
一次?使用那个 List ,然后扔掉。除非您需要同时添加、删除和获取随机元素... -
@spender 我只删除随机找到的元素
-
@Baldrick 我担心是后者。循环基本上是:选择一个随机单元格(哈希集包含随机洪水填充可以传播到的所有可能的单元格,“边缘”)->填充它->找到相邻的空单元格并将它们添加到哈希集中->删除填充来自 hashset 的单元格 -> 再次循环直到 hashset 为空
-
感觉二维链表在这里会成为你的朋友。
标签: c# performance random hashset