Представьте себе следующее дерево:
A
/ \
B C
/ \ \
D E F
Я ищу способ запросить, является ли, например, F потомком A (примечание: F не обязательно должен быть прямым потомком A), что в данном конкретном случае будет истинный. Необходимо протестировать только ограниченное количество потенциальных родительских узлов в сравнении с большим пулом потенциальных потомков.
При проверке того, является ли узел потомком узла в потенциальном родительском пуле, его необходимо проверить на ВСЕХ потенциальных родительских узлах.
Вот что придумал:
Преобразовать многоканальное дерево в трие, т. е. присвоить следующие префиксы каждому узлу в приведенном выше дереве:
A = 1 B = 11 C = 12 D = 111 E = 112 F = 121
Затем зарезервируйте битовый массив для каждого возможного размера префикса и добавьте родительские узлы для тестирования, т.е. если C добавлен в потенциальный пул родительских узлов, выполните:
1 2 3 <- Prefix length *[1] [1] ... [2] *[2] ... [3] [3] ... [4] [4] ... ... ...
При проверке, является ли узел потомком потенциального родительского узла, возьмите его префикс trie, найдите первый символ в первом «массиве префиксов» (см. выше) и, если он присутствует, найдите второй символ префикса во втором «префиксе». array" и так далее, т.е. проверка F приводит к:
F = 1 2 1 *[1] [1] ... [2] *[2] ... [3] [3] ... [4] [4] ... ... ...
так что да F, является потомком C.
Этот тест кажется наихудшим случаем O (n), где n = максимальная длина префикса = максимальная глубина дерева, поэтому его наихудший случай в точности соответствует очевидному способу просто подняться по дереву и сравнить узлы. Однако это работает намного лучше, если тестируемый узел находится в нижней части дерева, а потенциальный родительский узел находится где-то вверху. Комбинация обоих алгоритмов смягчит оба наихудших сценария. Тем не менее, накладные расходы памяти вызывают беспокойство.
Есть ли другой способ сделать это? Любые указатели с благодарностью!