我需要一个数据结构,该结构能够为给定的int结构的一部分提供前后邻居。
我为自己设定的一些标准:
写一次,读很多遍
包含100到1000个整数
高效:数量级O(1)
内存效率高(理想情况下,整数大小+一些管理位)
用纯Java实现(我想学习的没有库)
项目是独特的
没有并发要求
int是从外部订购的,该顺序很可能不是自然顺序,并且必须保留该顺序(即,关于两个相邻int之间的价值差异,没有任何合同-任何int都可以大于或小于int它按顺序排列)。
这是用Java语言编写的,并且基本上是理论上的,因为我已经开始使用下面描述的解决方案。
我考虑过的事情:
LinkedHashSet:非常快速地找到项目,顺序为O(1),并且非常快速地检索下一个邻居。如果没有对集合进行反向排序,没有明显的方法可以获取先前的邻居。仅装箱的整数对象。
int []:在内存上非常容易,因为不需要装箱,可以非常快速地获取上一个和下一个邻居,尽管由于不知道索引并且需要遍历数组,所以检索项目是O(n),这是不可接受的。
我现在使用的是int []和HashMap的组合:
HashMap,用于检索int []中特定int的索引
int []用于检索该int的邻居
我喜欢什么:
邻居查找理想情况下为O(2)
int []不会装箱
理论上表现很好
我不喜欢的是:
HashMap进行两次装箱(键和值)
整数被存储两次(在映射和数组中)
理论内存使用量可以大大提高
我很想知道更好的解决方案。
我现在使用的是int []和HashMap的组合:您可以显示尝试过的内容吗?
如何检索int[]项目O(n)?搜索项目是,但是检索是一个恒定时间的操作。
检索int[]的O(n)吗?不要这样想
是否需要存储int值的范围?他们可以在MIN_INT到MAX_INT或更少的范围内吗?
为了澄清问题而进行编辑:当我谈论int []和O(n)时,我的意思是搜索:我只有该项目,而没有它在数组中的索引,因此我首先需要进行搜索,这最多需要O (n)时间。我相信,从我其余的问题来看,这是显而易见的。
@AaronDigulla:我只能使用正整数(0 @Zaan如果必须搜索int[],则在最坏的情况下只有O(n)。如果确保插入时的排序顺序,则平均大小写为O(log(n))。
您担心记忆吗?请记住,除非您使用的是有限的体系结构(电话,ARM等)并且使用大型数据集,否则在任何较新的计算机上通常都不是问题。
@MadConan也许我错过了一些东西,但是由于我的主要要求是查找邻居(这是外部排序的结果),因此无法按其值对整数进行排序。
@MadConan不关心,我说我对理论上可能发生的事情感兴趣
@Zaan我不理解关于寻找邻居而不是根据价值进行排序的要求。这些整数代表什么?
@MadConan Ive试图对我的问题进行说明:整数是在各种字段中过滤和排序的项目的数据库ID:整数不是自然排序的,但是必须保留其顺序。
一种解决方案是在添加元素时对数组进行排序。这样,前一个元素始终为i-1,并且要查找值,可以使用二进制搜索O(log(N))。
下一个明显的候选对象是平衡二叉树。对于此结构,insert有点昂贵,但查找仍然是O(log(N))。
如果这些值不是32位的,则可以通过使用第二个数组来加快查找速度,其中每个值都是第一个数组中的索引,而索引是您要查找的值。
更多选项:您可以查看位集,但这又取决于值的范围。
Commons Lang有一个使用原始int作为键的哈希图:http://grepcode.com/file/repo1.maven.org/maven2/commons-lang/commons-lang/2.6/org/apache/commons/lang /IntHashMap.java
但类型是内部的,因此您必须复制代码才能使用它。
这意味着您无需自动装箱任何东西(拆箱很便宜)。
有关:
http://java-performance.info/implementing-world-fastest-java-int-to-int-hash-map/
HashMap和int作为键
ints are ordered externally, that order will most likely not be a natural ordering, and that order must be preserved (ie. there is no contract whatsoever regarding the difference in value between two neighboring ints).
这对我说"树"。就像亚伦(Aaron)所说的那样,插入成本很高,但查询效率很高,如果您只写一次,要读很多次,这就是您想要的。
编辑:多考虑一下这一点,如果一个值只能有一个孩子和一个父母,并考虑到您的所有其他要求,我认为ArrayList会很好地工作。即使它是O(n),也很简单而且非常快。但是,如果数据集增加,则使用Map-List组合可能会更好。
使用这些结构时,请记住,以O()表示的理论性能并不总是对应于实词性能。您需要考虑数据集的大小和整体环境。一个示例:ArrayList和HashMap。从理论上讲,List是O(n)用于未排序的查找,而Map是O(1)。但是,为地图创建和管理条目会产生大量开销,实际上,在较小的集合上,其性能要比列表差。
既然您说您不必担心内存,那么我将远离array。对于指定的数据集大小,管理大小的复杂性是不值得的。
"数组。管理大小的复杂性不符合您指定的数据集大小。" 好的,但是因为这是一次写入操作,所以我认为管理规模实际上不是问题(至少不是定义问题)。 另外,也许我还是误会了,但树是否暗示自然排序?
可以,但不是必需的。
@Zaan当您说"一次写入"时,我将其视为一次写入值。 如果有1000个值,那就是1000次写入。 在不了解所有细节的情况下,很难确定您需要什么。 但是使用原始数组通常是不值得的。
探讨了一种高效的数据结构设计,旨在快速查找给定整数的前后邻居,适用于固定且已排序的整数集合。对比了多种实现方案,包括LinkedHashSet、int[]及int[]与HashMap的组合。
1343

被折叠的 条评论
为什么被折叠?



