Я предполагаю, что верно следующее:
- График ациклический .Вы упомянули об этом в своем комментарии, но я хотел бы уточнить, что это исходное предположение.
- Существует известный набор корневых узлов .Нам нужен какой-то способ узнать, какие узлы всегда считаются достижимыми, и я предполагаю, что (каким-то образом) эта информация известна.
- Исходный граф не содержит лишних узлов .То есть, если исходный граф содержит какие-либо узлы, которые должны быть удалены, они уже были удалены.Это позволяет алгоритму работать, поддерживая инвариант, что каждый узел должен быть там.
Если это так, то при начальной настройке единственной причиной, по которой узел находится в графе, будетлибо
- Узел находится в наборе корневых достижимых узлов, либо
- Узел имеет родителя, который находится в наборе корневых достижимых узлов.
Следовательно, каждый раз, когда вы удаляете узел из графа, единственными узлами, которые могут потребоваться удалить, являются его потомки.Если удаляемый вами узел находится в корневом наборе, вам может понадобиться обрезать большую часть графа, и если удаляемый вами узел является узлом-потомком с несколькими собственными потомками, то вам может потребоваться сделать очень мало.
При такой настройке после удаления узла вам нужно будет отсканировать всех потомков этого узла, чтобы выяснить, есть ли у кого-нибудь из них другие родители, которые могли бы сохранить их в графе.Поскольку мы предполагаем, что единственными узлами в графе являются узлы, которые должны быть там, если дочерний узел удаленного узла имеет хотя бы одного другого родителя, он все равно должен быть в графе.В противном случае этот узел должен быть удален.Поэтому одним из способов сделать шаг удаления мог бы быть следующий рекурсивный алгоритм:
- Для каждого из дочерних узлов удаляемого узла:
- Если у этого узла ровно один родительский элемент:(это должен быть узел, который мы собираемся удалить)
- Рекурсивно удалить этот узел из графа.
- Удалить указанный узелиз графика.
Возможно, это не очень хороший алгоритм для непосредственной реализации, поскольку рекурсия может быть довольно глубокой, если у вас большой граф.Таким образом, вы можете реализовать его с помощью алгоритма рабочего списка, подобного следующему:
- Создать рабочий список W.
- Добавить v, удаляемый узел, к W.
- Пока W не пусто:
- Удалить первую запись из W;назовите его w.
- Для каждого из детей w:
- Если у этого ребенка только один родитель, добавьте его в W.
- Удалить w изграфик.
В конечном итоге это время O (m) в худшем случае, где m - число ребер в графе, поскольку в теории каждому ребру придетсябыть отсканированным.Однако это может быть гораздо быстрее, если предположить, что в вашем графике есть некоторые избыточности.
Надеюсь, это поможет!