Я строю графический редактор в Javascript, и мне нужен алгоритм, чтобы определить все возможные маршруты между двумя объектами 'узла'.

Учитывая следующий объект JSON:

{
    "failureNode": {
        "failureNode": {
            "failureNode": {
                "failureNode": {
                    "failureNode": null,
                    "successNode": null,
                    "id": "node-endpointfailure",}
                },
                "successNode": {
                    "failureNode": null,
                    "successNode": null,
                    "id": "node-endpointsuccess",
                },
                "id": "node-1",
            },
            "successNode": {
                "failureNode": null,
                "successNode": null,
                "id": "node-endpointsuccess",
            },
            "id": "node-2",
        },
        "successNode": {
            "failureNode": {
                "failureNode": {
                    "failureNode": null,
                    "successNode": null,
                    "id": "node-endpointfailure",
                },
                "successNode": {
                    "failureNode": null,
                    "successNode": null,
                    "id": "node-endpointsuccess",
                },
                "id": "node-1",
            },
            "successNode": {
                "failureNode": null,
                "successNode": null,
                "id": "node-endpointsuccess",
            },
            "id": "node-3",
        },
        "id": "node-4",
    },
    "successNode": {
        "failureNode": null,
        "successNode": null,
        "id": "node-endpointsuccess",
    },
    "id": "node-root",
}

Мне нужны все возможные маршруты между узлами с ID = 'node-root' & 'node-endpointfailure'. В этом примере есть два возможных способа начать с «Start» (который является корнем узла в структуре данных) и завершиться и «Failure» (node-endpointfailure):

  1. Пуск -> узел1 -> узел2 -> узел4 -> ошибка
  2. Пуск -> узел 1 -> узел 3 -> узел -> ошибка

Для этого примера выводом будет массив путей JSON. Что-то вроде этого...

[
    failureNode.failureNode.failureNode.failureNode,
    failureNode.successNode.failureNode.failureNode
]

Большая часть приложения использует jQuery, поэтому подойдет либо чистое решение Javascript, либо jQuery.

1
jungos 30 Янв 2013 в 21:54

2 ответа

Лучший ответ

Это должно сделать задачу:

function recurse(from, to, node) {
    var result = [],
        choices = ["sucessNode", "failureNode"];
    if (!from && to == node.id)
        return [[]];
    if (from == node.id)
        return recurse(null, to, node);
    for (var i=0; i<choices.length; i++) {
        var choice = choices[i];
        if (node[choice] != null) {
            var res = recurse(from, to, node[choice]);
            for (var j=0; j<res.length; j++) {
                res[j].unshift(choice);
                result.push(res[j]);
            }
        }
    }
    return result;
}
recurse('node-root', 'node-endpointfailure', data);
1
Bergi 30 Янв 2013 в 19:13

Я нахожу ваш выбор представления немного странным и запутанным. Дерево не является оптимальным способом представить это. То, что вы описываете, по сути является DAG (направленный ациклический граф). Рекурсивное представление в конечном итоге будет дублировать объекты. Хотя я уверен, что есть и другие способы представить это, простым представлением было бы просто перечислить каждый узел с его успешным и неудачным узлами, идентифицированными по id. Остановочные узлы будут иметь нулевые значения (или строки с нулевой длиной, в зависимости от того, что они есть) для их узлов успеха и неудач. Или вы можете иметь один словарь из них всех.

Например, ваш график может быть описан (в списке) как:

[
  {
    id: "Start",
    successNode: "success",
    failureNode: "node-1"
  },
  {
    id: "node-1",
    successNode: "node-3",
    failureNode: "node-2"
  },
  {
    id: "node-2",
    successNode: "success",
    failureNode: "node-4"
  },
  {
    id: "node-3",
    successNode: "success",
    failureNode: "node-4"
  },
  {
    id: "node-4",
    successNode: "success",
    failureNode: "failure"
  },
  {
    id: "success",
    successNode: "",
    failureNode: ""
  },
  {
    id: "failure",
    successNode: "",
    failureNode: ""
  }
]

Что позволяет довольно легко редактировать ваш график. Просто добавьте или удалите узлы и их значения в зависимости от ситуации. Я мог бы использовать другой объект в качестве словаря, чтобы было легче / быстрее находить каждый узел. Предположим, что у меня есть такой словарь dict, не составит труда перейти от узла к узлу, чтобы увидеть, где вы оказались.

1
JayC 30 Янв 2013 в 19:42