首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >一种高效的数据结构搜索算法

一种高效的数据结构搜索算法
EN

Stack Overflow用户
提问于 2012-05-31 07:00:22
回答 3查看 627关注 0票数 0

我正在尝试构建一个如下所示的数据树,我需要一个高效的匹配算法来完成以下任务。

您可以将此树视为参加课程的先决条件列表。例如,course1有前提条件3和4,课程3有前提条件7和8。如果想学习course1,他/她必须同时修3和4,或者course3或course4的所有前提条件(所以如果他/她修了7,8,4,相当于修了3和4)。

现在有个孩子来了,他说他想上course2,前提是他提前修了8、9和6门课。我如何快速检查他是否符合条件?

我现在能想到的唯一方法是构造一个包含所有先决条件组合的查找表,并检查它以找到匹配项。但是,随着树变得越来越大(我正在尝试构建一个可能超过10,000个节点的树),这种方法将会炸毁我的计算机。

有人对此有什么建议吗?或者更好的是,有没有定义良好的搜索算法已经可以处理这种类型的任务?提前谢谢。吉姆

图:一些任意数据树

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-31 07:11:57

只要以一种简单的方式来做,性能可能就会很好。如果学生想要2,首先检查它们是否满足5先决条件的要求,然后检查它们是否满足6先决条件的要求。您的需求检查函数将涉及递归调用或类似的调用。

如果由于某种原因不起作用(图中的循环?!),您可以按照您所描述的方向进行操作:从学生所学的课程开始,然后进行大量填充,以获得该学生符合条件的所有课程的列表。检查目标是否在该列表中(或者更确切地说:如果在构建列表时遇到目标,请立即停止)。

泛洪填充有些复杂,因为您不仅仅是在遵循箭头:我可以通过四种不同的方式符合1的条件:(3 or (7 and 8)) and (4 or 9)。但基本思想是相同的:不断测试我的可达节点的父节点,看看我是否可以将任何东西添加到我的集合中,直到我不能再添加为止。

适用于两种方法:我不完全清楚规则是什么,这个“满足3的前提条件而不是取3”是否是传递性的。给定:

代码语言:javascript
运行
复制
      1
     / \
    2   3
   /
  4
 / \
5   6

我知道拥有(5,6)使我有资格使用2,但是(5,6,3)使我有资格使用1

如果是这样,那么我认为这个过程会更容易一些,因为作为一个简化的假设,我可以假装如果我参加了(5,6),那么我也参加了4,然后是“我有资格申请2吗?”变成了,“我吃了2次了吗?”

对我来说,如果不这样做似乎更明智,因为我不认为我真的可以上一大堆初级课程,然后直接跳到更高10级的研究生工作中。然后,我学过的课程和我学过的必修课之间存在功能上的差异。这种差异需要被跟踪。在泛洪填充的情况下,我认为这意味着每个节点需要考虑2个标志,而不是1个。在需求检查功能的情况下,我认为这意味着您需要2个检查(直接和间接满足),并且不需要递归。

票数 1
EN

Stack Overflow用户

发布于 2012-05-31 07:11:18

“(所以如果他/她取7,8,4,相当于取了3和4)。”--原始海报

这不太像先决条件;正常的类不是这样工作的。这是一个可能的替换的列表。例如,你希望有一个2,但你也可以拥有2的所有替换,也就是5,6。你还可以用9,10代替5,或者11代替6。

这是可替换性的递归定义。

在python中:

代码语言:javascript
运行
复制
def canMake(desired, withIngredients):
    if desired in withIngredients:
        return True
    else:
        return all(canMake(s,withIngredients) for s in desired.substitutions)

附注:

您需要能够在O(1)时间内查询节点的父节点是什么。如果您将您的类定义为:

代码语言:javascript
运行
复制
2 requires 5,6
5 requires 9,10
...

如果你像这样存储它,它将要求你添加反向引用:

代码语言:javascript
运行
复制
5 allows 2
6 allows 2
9 allows 4,5

我们假设第一种情况,course.prereqs是所需类的列表(在第二种情况下,您可以通过为每个课程定义:course.parents = [],然后为每个课程的子类附加child.parents.push(child)来轻松地构建此列表)。

票数 0
EN

Stack Overflow用户

发布于 2012-05-31 07:43:23

直观的做法是通过BFS或DFS遍历树。

每当您到达表示您已经学习的课程的节点时,就剪切该节点下的所有节点。

因此,只有两种情况下资格检查失败:

  1. 到达表示您已选修课程的所有节点后,仍有其他节点要遍历。
  2. 您将到达一个叶节点,该节点不是表示您已选修课程的节点
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10825461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档