调查流程算法

时间:2017-01-19 15:50:41

标签: algorithm survey

我必须编写一个允许业务用户创建调查的工具。 如果填写调查的人员以特定方式回答了之前的问题,则只应询问一些问题。但无论选择的答案是什么,都应该显示一些问题。

到目前为止,我想出了一个图形结构,这是一个理想的例子:

(我只掌握图论的基本知识,所以请原谅选择可能不尽可能准确的单词)

enter image description here

A,B,C等轮次代表问题,链接上的值代表了访问问题的前提条件。

NULL表示没有前置条件和类似" 0"或" 1"意味着前一个问题必须有一个值#34; 0"或" 1"显示问题。

具体例子: 我在A轮。我有两个可能的答案。第一个的值为" 0"。第二个是" 1"的值。如果我选择有价值的答案" 0"然后我会去问B。

我现在在B轮。无论答案是什么,我都会去E轮,因为没有先决条件。

E是一个叶节点,所以我回到B. B有另一个子节点F,没有前提条件所以我转到问题F.让我们在那里结束流程。

我也可以有一个有多个前提条件的问题。这由问题N表示。只有在答案为" 5"关于问题F和" DE"问题I.在这种情况下,在回答问题F之后,由于在这个状态下只有一个前提条件有效,我们将在图表中返回并且仅在回答" DE"问题是我们可以转向问N.

我的问题是关于用于此类调查的算法。是否存在涵盖此用例的现有算法?我认为这看起来像是DFS图遍历,但条件让我怀疑。

另外,我是否过于复杂,可以更简单地表达一下吗? 我现阶段非常喜欢一些建议。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

根据您的描述,我会稍微改变您提出的图表的概念:

  • 将其设为有向图(即每个弧都有源和目标的图形)。
  • 每个问题有一个节点,每个答案一个节点(每个问题的每个答案都是不同的节点)。每个问题节点都需要有一个标志来确定它是否是"问题类型"或"回答类型"以及一个标记是否已被访问的标志。
  • 每个问题节点都会连接到每个问题的答案(方向[问题] - > [答案])。
  • 每个答案前提条件("达到问题B,您需要回答问题A和#34中的0;)将由一个答案的弧(节点[问题A的答案0])表示为问题"解锁" (节点[问题B])。如果一个问题需要几个答案,它将有几个传入的弧。
  • 每个问题的前提条件("达到问题D,你需要回答问题A,无论选择")都会用一个问题(节点[问题A])到另一个问题的弧来表示(节点[问题D])。

然后算法将沿着以下几行:

  1. 拥有一堆待定节点 P ,最初包含与第一个调查问题对应的节点。
  2. 弹出 P 的第一个元素, Q ,它应该始终是一个问题节点,并将其标记为已访问。
  3. 获取 Q (通过传出弧连接到当前节点的节点)的后继列表,并将其拆分为&#34; answer successors&#34;, QtoA < / em>,&#34;质疑接班人&#34;, QtoQ
  4. QtoQ 中的所有元素添加到 P (如果有任何方法可以将这些元素排序,例如某些&#34;问题ID&#34;,确保它们以第一个元素在堆栈顶部结束的方式添加。)
  5. 提出问题(您甚至可以将问题存储在图表中,并从中检索所需的所有信息)。
  6. QtoA 获取所选答案 A 的节点,将其标记为已访问并依次收集其所有后继者的列表 AtoQ
  7. 对于 AtoQ 中的每个节点 R (如果有的话,再次考虑在此处排序),如果所有 R 的前身(即通过传入弧连接到 R 的节点被标记为已访问,然后将 R 添加到 P
  8. 如果 P 中有任何节点,请转到步骤2.
  9. 这应该重现您描述的顺序。如果你想有能力获得几个可能的解锁答案(例如&#34;来自A,如果你回答1或2和#34,你会去B;)你需要做更多的调整(即,在第6步)你需要将&#34;访问过的&#34;检查&#34;回答类型&#34; R 的前身替换为&#34; R 可以通过 R &#34;)的前身的前任访问过的节点访问,但仍然可以使它工作。

    也许您已经了解它,但如果您有兴趣将图形用作唯一的数据源(可能是也可能不是这种情况),您可能会发现有趣的面向图形的数据库,如Neo4j

答案 1 :(得分:0)

以下是我如何解决问题的一般想法。

根据您提供的图表,我假设对于每个问题(节点),您可以告诉给定答案,哪些问题(节点)可能会被解锁。通过“可能解锁”,我的意思是他们实际上已经解锁,或者您刚刚遇到解锁问题的其中一个条件。

另一方面,您可以为每个问题存储解锁时需要满足的条件数(让我们将其命名为计数器)。然后,每当你得到答案时,你都会检查可以通过这个答案解锁的问题列表,然后你减少他们的计数器。

当任何计数器减少到零时,您将未锁定的问题添加到队列或堆栈(您可以选择是否更喜欢FIFO或LIFO订单)。当然,您从包含无条件问题的队列开始(在您的情况下仅为“A”)。

使用FIFO(队列),您将获得遍历图表的类似BFS的顺序。使用LIFO(堆栈),您将获得类似DFS的订单。无论你方便什么。