在基于树的结构中继承属性的最佳方法是什么?

时间:2011-03-11 06:07:30

标签: algorithm data-structures tree

我有一个简单的CMS系统,它有一个简单的树层次结构:

我们的页面A到E具有以下层次结构: A - > B - > C - > D - > ë

所有页面都是同一个类,并且具有父子关系。

现在,假设我有一个我希望在页面中继承的属性。我们说A是红色的: A(红色) - > B - > C - > D - > ë

在这种情况下,B到E将继承“红色”。

或更复杂的情况: A(红色) - > B - > C(蓝色) - > D - > ë

B会继承红色,而D / E都是蓝色。

解决这类问题的最佳方法是什么?我有一个树形结构,有超过6,000片叶子,其中约有100片叶子具有遗传特性。那些100左右的叶子的属性保存在数据库中。对于没有显式属性的叶子,我查找祖先并使用memcached来保存属性。然后有非常复杂的算法来处理那些缓存到期。这非常令人费解,我想重构一个更清洁的解决方案/数据结构。

有人有什么想法吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

如果您的问题与性能有关......

我假设你想要保存所有这些可继承属性的内存(或者你可能有 lot ),否则这可以通过虚拟属性轻松解决。

如果您需要稀疏的可继承属性,比如说您正在建模HTML DOM属性或CSS属性的传播方式,则需要:

  1. 保留指向父节点的指针(向上行走)
  2. 使用哈希字典存储每个类(或每个实例,根据您的需要)中的属性,按名称键入
  3. 如果属性不因实例而异,请使用类静态字典
  4. 如果可以逐个实例覆盖属性,请在顶部添加实例字典
  5. 访问属性时,开始在叶子上找到它,首先查看实例字典,然后查看类静态字典,然后向上走树
  6. 当然,您可以在此基础上添加更多功能。这与Windows Presentation Foundation通过DependencyProperty解决此问题的方式类似。

    如果您的问题与数据库相关......

    如果您的问题是避免读取数据库以使树向上(即加载父项以查找继承的属性),则需要对父值执行某种缓存。或者,当您从数据库加载叶子时,您可以加载其所有父项并在内存中创建主合并属性字典。

    如果要避免多个数据库查找以查找每个父节点,一个技巧是将每个节点的路径编码为文本字段,例如: “1.2.1.3.4”对于第6级的叶子。然后,仅加载具有开始子串的路径的节点。然后,您可以在一个SQL查询中获取整个父路径。

答案 1 :(得分:2)

有一种数据模型可以让您完美地表达这种信息,即RDF / RDFS。 RDF是W3C标准,用于根据三元组(主题,谓词,对象)和URI对数据建模;除其他外,RDFS允许您描述类层次结构和属性层次结构。好消息是,有许多库可以帮助您创建和查询此类数据。

例如,如果我想说某个特定文档Lion属于班级Animalprogrammer属于班级Geek,我可以说:

doc:lion rdf:type class:mamal .
doc:programmer rdf:type class:Geek .

现在我可以宣布一个类的层次结构,并说每个mamal都是动物,每个动物都是生物。

class:mamal rdfs:subClassOf class:animal .
class:animal rdfs:subClassOf class:LivingThing .

而且,每个极客都是人,每个人都是生物:

class:geek rdfs:subClassOf class:human .
class:human rdfs:subClassOf class:LivingThing .

有一种类似于SQL的语言,称为SPARQL来查询此类数据,例如,如果我发出查询:

SELECT * WHERE {
       ?doc rdf:type class:LivingThing .
}

其中?doc是一个将class:LivingThing的事物类型绑定的变量。我会得到这个查询doc:liondoc:programmer的结果,因为数据库技术将遵循RDFS的语义,因此通过计算类的闭包,它将知道doc:lion和{{ 1}}是doc:programmer

以同样的方式查询:

class:LivingThing

请告诉我SELECT * WHERE { doc:lion rdf:type ?class . } doc:lion rdf:type class:mamalclass:animal。{/ p>

就像我刚才解释的那样,使用RDFS,您可以创建属性的层次结构,并说:

class:LivingThing

我们可以说,doc:programmer doc:studies doc:computerscience . doc:lion doc:instint doc:hunting . doc:skill属性都是doc:instint的子属性:

doc:knows

使用查询:

doc:studies rdfs:subPropertyOf doc:knows .
doc:instint rdfs:subPropertyOf doc:knows .

我们会让狮子知道如何打猎,程序员也知道计算机科学。

大多数RDF / RDFS数据库可以轻松处理您在问题中提到的元素数量,并且有很多选择可以开始。如果您是Java人员,可以查看Jena,还有.Net lije this one或Python RDFLIB的框架

但最重要的是,请查看CMS的文档,因为可能有插件将元数据导出为RDF。例如,Drupal在这种情况下非常先进(见http://drupal.org/project/rdf