Data structures 对象类索引的数据结构
我希望能够保持对象的集合,并根据对象的类型对其进行查找,其中类型可以是层次结构的,就像多重继承OO系统中的类一样 现在,我只需保留一个对象列表,然后循环遍历,查询每个对象,看看它是否属于请求的类型,类似于这样,在类似Python的伪代码中:Data structures 对象类索引的数据结构,data-structures,language-agnostic,Data Structures,Language Agnostic,我希望能够保持对象的集合,并根据对象的类型对其进行查找,其中类型可以是层次结构的,就像多重继承OO系统中的类一样 现在,我只需保留一个对象列表,然后循环遍历,查询每个对象,看看它是否属于请求的类型,类似于这样,在类似Python的伪代码中: def hastype(对象,类型): 对于对象中的obj: 如果存在(对象,类型): 返回obj 一无所获 通常这对我来说并不是一个特别的问题,但是在有些情况下,能够更有效地进行这些查找会很好 如前所述,我的类型与多重继承系统中的类非常相似;每个类型声明
def hastype(对象,类型):
对于对象中的obj:
如果存在(对象,类型):
返回obj
一无所获
通常这对我来说并不是一个特别的问题,但是在有些情况下,能够更有效地进行这些查找会很好
如前所述,我的类型与多重继承系统中的类非常相似;每个类型声明任意数量的直接超类型,并提供这些类型中直接和间接超类型的完整列表。有一个类型root。我可以轻松地查询类型的超类型的完整列表。我还拥有系统中所有已知类型的全局知识,每个类型都有一个整数ID,如果有帮助的话,这些ID是连续分配的
我关心的主要特性是无论集合中有多少个对象都可以快速查找(不需要是O(1),但最好是比O(n)更好的),但我也非常关心有效的插入和删除(最好不管集合中有多少个对象,也不管对象类型中有多少个超类型,但我愿意相信这些标准可能是相互排斥的),以及使用的内存量
我已经搜索了一些已经发明的此类数据结构,但没有找到任何;我也没有想到任何适合我上述需求的数据结构(例如,给定连续的类型ID,使用O(1)可以轻松地创建从类型到对象的直接查找表)查找,但这会占用太多内存)
有人知道或能想到这种数据结构吗?好的,我来试试。如果你担心内存限制,那么它可能不是你想要的 下面是一些ruby-ish代码:
# 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)。您只需计算每个类型和每个对象的开销,将其乘以预期的类型和对象数,然后从中做出决定
我能想到的所有解决方案都需要一个哈希表,因此如果哈希表有太多的内存开销,那么我就没有主意了。汤姆·达林的方法在内存开销方面非常接近最优。然而,正如前面提到的,有一些算法可以用这些开销换取更快的超类型,并计算一个类型的直接/间接超类型的数量has.下面是一些这样做的算法,由您来决定是否值得权衡。最后,两种算法的性能在很大程度上取决于类型图(子类型和超类型之间的连接)的外观。如果类型图是相当空闲的或其他有利的(与性能相关的变量更接近性能界限的下限),那么以下算法的平均(摊销)性能可以使它们值得使用 绩效相关变量:
- N是类型数
- D是平均深度(子类型向下延伸的距离)。边界O(1)到O(N)
- M是编号最高的ID的值,该ID是给定类型的子类型。边界为O(1)到O(N)
- k是一个类型具有的直接超类型的数目。界为O(1)到O(N)
- K是一个类型具有的唯一超类型总数的平均数。界为O(1)到O(N)
- L是一个类型具有的唯一子类型总数的平均数。边界为O(1)到O(N)
- E是子类型超类型连接的数量。边界为O(N)到O(N^2)
return len(supertype_array) > supertype_id and supertype_array[supertype_id] is True
添加子类型等于在每个直接超类型的“超类型”列表上执行集合并集,即O(k*N)