我希望能够保持对象的集合,并根据对象的类型对其进行查找,其中类型可以是分层的,就像多继承OO系统中的类一样。
现在,我只需保留一个对象列表,然后循环遍历,查询每个对象是否属于所请求的类型,类似于Python的伪代码:
def hastype(objects, type):
for obj in objects:
if isinstance(obj, type):
return obj
return None
通常情况下,这对我来说不是一个特别的问题,但是在某些情况下,能够更有效地进行这些查找是很好的。
如前所述,我的类型非常类似于多继承系统中的类;每个类型声明任意数量的直接超级类型,并从这些类型中获得一个完整的直接和间接超级类型列表。有一个类型根。我可以很容易地查询一个类型的超级类型的完整列表。我还了解系统中所有已知类型的全局知识,其中每个类型都有一个整数ID,如果这有帮助,则会连续地分配ID。
我关心的主要特性是快速查找,而不管集合中有多少对象(它不需要是O(1),但是比O(n)更好的东西会更好),但我也非常关心高效的插入和删除(最好不管集合中有多少对象和对象的类型中有多少超级类型,但我愿意购买这些标准可能是相互排斥的),以及使用的内存数量。
我搜索了一些已经发明的此类数据结构,但我没有找到任何这样的数据结构;我也没有很好地想到符合我的需求的任何我自己(例如,考虑到连续的类型I,创建一个从类型到O(1)查找对象的直接查找表很容易,但这会占用太多内存)。
有人知道或能想到这种数据结构吗?
发布于 2014-03-08 10:21:36
好的,我来试一试。如果您担心内存限制,那么它可能不是您想要的。
下面是一些红宝石代码:
# hash of all objects by type
#
# heirarchy:
#
# animal
# amphibian
# mammal
# hominid
#
objects_by_type = {
animal: [:snake, :fish]
amphibian: [:frog, :newt]
mammal: [:whale, :rabbit]
hominid: [:gorilla, :chimpanzee]
}
# print all objects that are of type `search_type`, or a subtype of `search_type`
def print_objects_of_type(search_type)
#get a list of all valid types
all_types = [search_type] + search_type.subtypes
#print all objects belonging to a type in all_types
all_types.each do |t|
objects_by_type[t].each do |obj|
print obj.to_s + ' '
end
end
print "\n"
end
print_objects_of_type(:animal)
# snake fish frog newt whale rabbit gorilla chimpanzee human
print_objects_of_type(:mammal)
# whale rabbit gorilla chimpanzee human
print_objects_of_type(:amphibian)
# frog newt
所有这些都依赖于散列,其中键是类型,值是对象的列表。
搜索给定类型的对象将比O(n)更好,因为您直接进入正确的对象,而不测试不正确的对象。散列查找将是O(1),其余的取决于获得给定类型的子类型列表的速度。
对于插入和删除,只要对象列表是链接列表,就应该能够实现O(1)。插入和删除将需要一个哈希表查找(O(1))和一个插入/删除链接列表(也是O(1))。
现在,唯一的问题是这种方法所需的内存量。类型的数量影响哈希表内存的使用,对象的数量影响链接列表内存的使用。您可以用连续内存(如C++ std::vector)替换链接列表,这可以消除每个对象的开销,但是插入/删除将不再是O(1)。您只需计算每个类型和每个对象的开销,乘以预期的类型和对象数,然后从那里做出决定。
我能想到的所有解决方案都需要一个哈希表,所以如果这有太多的内存开销,那么我就没有想法了。
发布于 2014-03-10 12:36:08
就内存成本而言,汤姆·达林的方法相当接近最优。但是,正如前面提到的,有些算法可以用这些代价来换取更快的超级类型和计算一个类型所拥有的直接/间接超级类型的数量。下面是几个这样做的算法,这取决于您决定是否值得这样做。最后,这两种算法的性能在很大程度上取决于类型图(子类型和超类型之间的连接)是什么样的。如果类型图是相当多余的或其他有利的(与性能相关的变量更接近性能界限的下限),那么以下算法的平均(摊销)性能可以使它们值得使用。
与业绩有关的变量:
算法:
这两种算法的插入/删除成本与Tom Dalling的相同,尽管基函数Trie可能更快/更节省空间。也不难为每种类型保留一个超级类型数量的计数器,但这需要额外的O(N log N)额外空间。
注意,尺寸要求假定最小位数用来表示一个数字,以最小化空间。从这些不重要的位数中删除不应超过O(log )的因子对时间性能的影响。
https://stackoverflow.com/questions/22267342
复制相似问题