Я хотел бы повернуть влево поддерево с корнем в узле N
(см. рисунок слева) без манипуляций с родителем P
,
P P P
\ | \
N | R R
/ \ |/ /
L R N N
/ /
L L
Если я буду к нему в функции, которая занимает N
в качестве аргумента:
void rotate_left(Node *node);
Я закончу деревом, представленным на средней фигуре. Проблема в том, что несмотря на вращение P
еще указывает на N
не R
(левая фигура). Как сделать P
указывая на R
в конце вращения, если функция rotate_left()
не имеет указателя на P
?
Я думаю о трех способах сделать это:
Позволять rotate_left()
принимает ссылку на указатель на узел N
void rotate_left(Node * &node);
Тогда позвони rotate left()
Минуя правильное дитя P
(то есть
N
):
rotate_left(P->right_child);
Поместить объект R
под адресом памяти N
в конце
вращение
Передать родительский P в rotate_left()
:
void rotate_left(Node *parent, Node *child);
Решения (2) и (3) звучат не очень хорошо, и в решении (1) нужно знать родителей P
в функции, которая вызывает rotate_left()
,
Решение 1 — лучшее из трех, которые вы предлагаете. Это более или менее эквивалентно решению 3. Я бы использовал это. Мне кажется что везде звонишь rotate_left
Вы уже знаете переменную, в которой хранится этот указатель (либо родительский узел, либо root
), так что это не будет проблемой, передавая его ссылку.
Решение 2 (замена содержимого) сделает недействительными любые указатели, которые уже существуют за пределами вашего дерева. Вы должны быть очень осторожны; если есть такие указатели, не используйте их. Однако это единственный верный ответ на ваш вопрос «как вращаться, не зная родителя?».
Я полагаю, вы не захотите хранить указатели на родительские узлы в дереве. Если вы готовы сделать это, все будет намного проще.
Других решений пока нет …