2016-04-13 7 views
1

Так что у меня возникли проблемы с поиском правильного предка в 2-3 Дереве. В 2-3 Дереве произвольной высоты есть несколько случаев, чтобы искать.Поиск правильного предка в 2-3 Дереве

enter image description here

Мои узлы спроектированы следующим образом:

template<typename DataType> 
struct node{ 
    Node<DataType> *child1; //left-child 
    Node<DataType> *child2; //middle-child (3-node only) 
    Node<DataType> *child3; //right-child 
    Node<DataType> *extraChild; //for splitting purposes 

    Node<DataType> *parent; 

    DataType key1; //key1 <= key2 
    DataType key2; //key2 <= extraKey (only when node needs to be split) 
    DataType extraKey; //for splitting purposes 
}; 

Есть ли алгоритм или что-то подобное, чтобы найти правильный предка к узлу?

Например, скажем, что мы искали предка H (внизу предоставленного дерева), с визуальной точки зрения очевидно, что предком H является H в корне дерева. Но для этого требуется вскакивание 4 родительских ссылок. Дерево может быть произвольного размера, что является проблемой.

Моя цель в конце - создать итератор, который совершает обход 2-3 дерева. Цель поиска узла-предка заключается в том, что узел-предок будет преемником в последовательности листового узла, который является правильным потомком его родительского узла. Опять же, как в приведенном выше примере.

ответ

2

Если цель состоит в том, чтобы просто пересечь 2-3 дерева в порядке, вам просто нужно написать рекурсивную функцию, которая начинается с корня.

алгоритм выглядит следующим образом:

traverse(Node n) 

    if n.left != null 
     traverse(n.left) 

    if n.middle != null 
     visit(n.key1) 
     traverse(n.middle) 
     visit(n.key2) 
    else 
     visit(n.key1) 

    if n.right != null 
     traverse(n.right) 

Algorithm taken from this link.

+0

К сожалению, это не ответ на мой вопрос. Я не пытаюсь добиться «одноразового» обхода в порядке. Я создаю объект, который содержит состояние в любом месте в дереве. С этого места объект мог бы перейти к преемнику, и, если бы не было больше преемников, верните прошлое итератору конца, null. – Saggitori

+0

Тогда заявленная цель в вашем исходном сообщении неверна: вы не пытаетесь создать итератор, который выполняет обход в 2-3 дерева. Если вам нужно найти самый последний родитель, который удовлетворяет некоторому ограничению (например, наличие эквивалентного ключа), то наиболее эффективным способом сделать это является просто выполнить сканирование через родительские ссылки, которые вы уже создали, который будет масштабироваться в логарифмическом времени с размером дерева. –

+0

Точно, какой алгоритм, который вы предоставили, не учитывается. Например, если мой итератор находится на листе N в приведенном примере, то преемником должен быть внутренний узел O. Говорить «обходить резервную копию родительского узла» отлично, он работает, но мне нужно иметь возможность сделать это из области узел N. Node N не знает, какой дочерний элемент он или из какой ветви он пришел. Все, что он знает, это то, что его родитель является внутренним узлом M. Мне нужно остановиться на O, возвращаясь через родителей и сравнивая значения, но с повторениями это может стать опасным. – Saggitori