我有一个大的2D网格,x-by-y。应用程序的用户将添加有关此网格上特定点的数据。遗憾的是,网格太大而无法实现为大型x-by-y阵列,因为运行它的系统没有足够的内存。
实现这一点的好方法是什么,只有添加了数据的点才会存储在内存中?
我的第一个想法是创建数据点的BST。诸如“(long)x<< 32 + y”的散列函数将用于比较节点。
然后我得出结论,如果不平衡,这可能会失去效率,所以我想出了具有可比BST点数的BST的想法。外部BST将根据它们的x值比较内部BST。内部BST将比较点的y值(并且它们都具有相同的x)。因此,当程序员想要查看(5,6)处是否存在点时,他们会查询外部BST为5.如果在该点存在内部BST,则程序员将查询内部BST为6.结果将被退回。
你能想到更好的实现方法吗?
编辑:关于HashMaps:大多数HashMaps都需要有一个数组用于查找。有人会说“data [hash(Point)] = Point();”设置一个点然后通过散列找到Point来查找索引。然而,问题是数组必须是散列函数范围的大小。如果此范围小于添加的数据点总数,则它们将没有空间或必须添加到溢出。因为我不知道将要添加的点数,所以我必须假设这个数字小于一定数量,然后将数组设置为该大小。同样,这实例化了一个非常大的数组(尽管假设数据点的数量比x * y少,但比原来要小)。我希望结构能够与数据量成线性比例,并且在空的时候不会占用大量数据。
看起来我想要的是SparseArray,正如一些人所提到的那样。它们的实施方式类似于在BST内部使用BST吗?
Edit2:Map<>是一个界面。如果我使用Map,那么它看起来像TreeMap<>这将是最好的选择。所以我最终会得到TreeMap< TreeMap的<点> >,类似于Map<地图<点> >人们提出的建议,基本上是BST内部的BST。谢谢你的信息,因为我不知道TreeMap<>基本上是BST的Java SDK。
Edit3:对于那些可能关心的人,选择的答案是最好的方法。首先,必须创建一个包含(x,y)并实现可比较的Point类。可以通过诸如(((长)x)<< 32)+ y)之类的东西来比较Point。然后,TreeMap会指向数据。搜索这个是有效的,因为它在一个平衡的树中,因此log(n)成本。用户还可以使用TreeMap.entrySet()函数查询所有这些数据,或者遍历它,该函数返回一组Points以及数据。
总之,这允许稀疏数组的空间效率和搜索效率的实现,或者在我的情况下,2D数组,也可以有效地迭代。
答案 0 :(得分:5)
将大点阵列的索引存储到其中一个空间结构中。 如果数据不是平均分布的话,这种空间结构是有利的,例如集中在城市中的地理数据,并且在海中没有任何意义。
想想你是否可以忘记常规网格,并使用四叉树 (想想,为什么你需要一个规则的网格?一个规则的网格通常只是一个简化)
在任何情况下都不要使用Objects来存储Point。 这样的Object只需要20个字节,因为它是一个对象!对于庞大的数据集来说,这是一个坏主意。
int x[]
,int[] y
或int[]xy
数组与内存使用情况相关。
考虑阅读
Hanan Samet的“多维数据结构的基础”
(至少是介绍)。
答案 1 :(得分:4)
您可以使用Map<Pair, Whatever>
来存储数据(您必须编写Pair类)。如果您需要按特定顺序迭代数据,请进行配对Comparable
,然后使用NavigableMap
答案 2 :(得分:2)
一种方法可能是Map<Integer, Map<Integer, Data>>
。外部映射上的键是行值,内部映射中的键是列值。与该内部地图关联的值(在这种情况下为Data
类型)对应于(row, column)
处的数据。当然,如果您正在尝试进行矩阵运算等,这将无济于事。为此你需要稀疏矩阵。
另一种方法是将行和列表示为Coordinate
类或Point
类。您需要实施equals
和hashCode
(应该非常简单)。然后,您可以将数据表示为Map<Point, Data>
或Map<Coordinate, Data>
。
答案 3 :(得分:1)
您可以拥有一个对象列表列表,该对象可以对其水平和垂直位置进行编码。
class MyClass
{
int x;
int y;
...
}
答案 4 :(得分:0)
也许我在这里过于简单,但我认为你可以使用常规HashMap
。它将包含自定义Point
个对象作为键:
class Point {
int x;
int y;
}
然后重写equals方法(以及hashCode方法),使其基于x
和y
。这样,您只能存储包含某些数据的点。
答案 5 :(得分:0)
我认为你是以正确的方式以高效的方式执行此操作 - 它可以通过使用地图映射相当容易地实现,包含在类中以便为查找提供干净的界面。
另一种(更有效的内存)方法是使用单个映射,其中键是元组(x,y)。但是,如果您需要进行“给我所有值x == some value
”这样的查询,这将不太方便。
答案 6 :(得分:0)
您可能希望查看Matrix toolkit project中的FlexCompColMatrix,CompColMatrix和其他稀疏矩阵实现。
性能将取决于写入/读取比率和矩阵的密度,但如果您使用矩阵包,则通过切换实现更容易进行实验
答案 7 :(得分:0)
我建议您使用Commons Math: The Apache Commons Mathematics Library。因为它可以通过利用您的应用程序所需的数学力量来节省您的一天。