Обход части элементов графа для загрузки всех родителей

Есть набор элементов ориентированного графа. Каждый элемент содержит ссылки на родительские элементы (которых может и не быть в наборе). И есть функция, которая может вернуть по идентификатору элемента все его родительские (вплоть до корневого элемента). Цель - минимизировать вызовы этой функции. Т.е. например, в такой ситуации
ситуация №1

логично вызвать функцию только для Node4 (в результате функция вернет все ноды - 1-5).

А в ситуации №2

ситуация №2

вероятно функцию нужно вызывать для всех элементов в наборе.

Видится такой алгоритм:

  1. для каждого элемента в наборе проверить наличие на него ссылки в других элементах набора
  2. при отсутствие ссылок поместить элемент в очередь
  3. для элементов в очереди вызывать функцию
  4. проверить наличие в результах вызовов функции наличие элементов, на которые ссылаются элементы набора, для которых вызова не было
  5. при обнаружении ссылки на элемент, который до сих пор не был получен, делать вызов для элемента набора с этой ссылкой и снова переходить к п.4

Только тут возможна ситуация, когда все элементы имеют ссылку друг на друга (это невозможно в рамках бизнес-логики, но все же не хочется ограничивать алгоритм). Ее нужно обработать отдельно. Подскажите, верно ли расуждаю, кажется это все уже должно быть придумано и не нужно ничего изобретать.

UDP. Реализовал алгоритм по комментарию @Stanislav Volodarskiy

Для набора элементов сделать топологическую сортировку. По полученному списку пройтись с конца. Для каждого элемента вызывать функцию поиска предков. Найденных предков из списка вычеркивать. Алгоритм гарантирует минимальное количество вызовов функции.

Но получается, что, например, в такой ситуации: ситуация №3

выполнив сортировку исходного набора, нужно будет вызвать функцию получения предков для одной из нод (Node1 или Node2 в зависимости от сортировки), результат вывоза функции будет содержать Node4, Node3, Node1 (или Node2). Вычеркнуть из набора мы ничего не сможем, т.к. второго элемента исходного набора в результатах вызова функции нет, а значит нужно выполнить еще один вызов функции для второго элемента в наборе (хотя этот вызов очевидно избыточен!).

Подскажите, правильно ли я понял алгоритм @Stanislav Volodarskiy или это ограничение этого алгоритма?


Ответы (0 шт):