Скажем, у нас есть функция verticesWithin(d,x)
, которая находит все вершины на расстоянии d
от вершины x
.
Одной из хороших стратегий решения такой проблемы, как раскрытие возможностей кэширования / запоминания, является задание вопроса: Как подзадачи этой проблемы связаны друг с другом?
В этом случае мы можем видеть, что verticesWithin(d,x)
, если d >= 1
- это объединение vertices(d-1,y[i])
для всех i
в пределах диапазона, где y=verticesWithin(1,x)
. Если d == 0
, то это просто {x}
. (Я предполагаю, что вершина считается на расстоянии 0 от себя.)
На практике вы захотите посмотреть список смежности для случая d == 1
, а не использовать это отношение, чтобы избежать бесконечного цикла. Вы также захотите избежать избыточности, считая x
самим членом y
.
Кроме того, если тип возвращаемого значения verticesWithin(d,x)
изменяется с простого списка или набора на список d
наборов, представляющих увеличивающееся расстояние от x
, то
verticesWithin(d,x) = init(verticesWithin(d+1,x))
где init
- функция, которая возвращает все элементы списка, кроме последнего. Очевидно, что это будет неразрывное рекурсивное отношение, если оно будет транскрибировано буквально в коде, поэтому вы должны быть немного сообразительны о том, как вы его реализуете.
Благодаря этим отношениям между подзадачами мы можем теперь кэшировать результаты verticesWithin
и использовать эти кэшированные результаты, чтобы избежать выполнения избыточных обходов (хотя и за счет выполнения некоторых операций над множествами - я не совсем уверен, что это победа). Я оставлю это как упражнение, чтобы заполнить детали реализации.