C ++ AVLTree Rotation

0

Я пытаюсь сделать LeftRotation с помощью своего AVLTree. Я вложу 3, 5, а затем 10, чтобы он стал вырожденным деревом. Когда я пройдусь, это даст мне 3, 5, 10 но когда я сделаю поворот, я получаю 5, 10 вместо ожидаемых 5, 3, 10.

Это что - то делать с установкой a качестве b left ветки. Я пройду через него, а корень моего дерева будет равен 5, слева будет 3, а справа будет 10, но когда я иду, чтобы пройти, он показывает, что левая сторона равна null.

Вот мой код вращения:

void AVLTree::RotateLeft(Node *root)
{
    Node a = *root;
    Node b = *root->GetRight();
    *root = b;
    a.SetRight(b.GetLeft());
    b.SetLeft(&a); //This is where the problem occurs
}

И мой код Traversal:

void AVLTree::Traverse(Node *node)
{
    cout << node->GetValue() << ", ";
    if (node->GetLeft() != nullptr)
        Traverse(node->GetLeft());
    if (node->GetRight() != nullptr)
        Traverse(node->GetRight());
}

Заранее спасибо!

Изменение: изменил все 0 на nullptr, спасибо за исправление!

  • 1
    Пока используется стандарт C ++ 11, используйте nullptr . Для более подробной информации: что такое nullptr? , Если нет, то лучше использовать макрос NULL . Весьма вероятно, что сравнение указателей с нулем будет стоить очков.
  • 0
    Кажется, что вы хотите сделать b.SetLeft(a) , а не &a . SetLeft принимает Node , а не Node* . Если возможно, вам также следует заменить все Node* на Node& в вашей программе, потому что вы используете указатели, как если бы они были ссылками ...
Показать ещё 3 комментария
Теги:
avl-tree

1 ответ

1
Лучший ответ

Существует проблема с перемещением root чтобы указать на новое местоположение. Если есть сомнения в этом, рассмотрите следующие два утверждения. Обратите внимание, что соглашение об именовании переменных из исходного кода выше используется для согласованности.

*root = b; // (1)
root = &b; // (2)

В (1) содержимое корневого указателя модифицируется так, чтобы содержать значение, сохраненное в переменной b. Адрес root не был каким-либо образом изменен. root адреса перед выполнением (1) остается неизменным после завершения (1).

В (2) root теперь указывает на адрес переменной b. Поскольку адрес, в котором указывается root, был изменен, содержимое root указателя теперь равно значению в переменной b.

Я настоятельно рекомендую по void AVLTree::RotateLeft(Node *root) через void AVLTree::RotateLeft(Node *root) и проверять адреса и содержимое всех переменных, чтобы увидеть это из первых рук. Я выполнил симуляцию вышеупомянутых действий над образцами целочисленных данных, и указатели перемещались, как ожидалось, используя (2).

До того, как произойдет ротация данных образца, ожидается, что небалансное дерево должно быть организовано таким образом, чтобы на 3 узлах был указан root. Затем root->right указывает на 5, а root->right->right указывает на 10. root->right->left должен быть nullptr, а root->left также должен быть nullptr.

Если это не так, то либо алгоритм вставки AVL реализуется неправильно, либо требования к дизайну отличаются от ожидаемого (например, дерево AVL в Википедии, структуры данных и анализ алгоритмов в C++ (3-е издание) [в твердом переплете] Марк Аллен Вайс, Учебник по дереву AVL по вечно смущенным Жюльеном Уокером).

Что касается перемещения балансировки дерева, где конечный результат равен root 5, то root->left указывает на 3 и root->right указывает на 10, правый указатель переданного в root указателе будет установлен на укажите левый указатель локального указателя pB (см. ниже), левый указатель pB будет указывать на переданный в root указатель, а root будет установлен на локальную переменную pB (изначально установленную в root->right указатель в этом случае).

Используя вышеприведенные данные, тело функции изменяется. Обратите внимание, что это не согласуется с тем, как GetRight() и GetLeft() возвращают копию узла в исходном сообщении выше. Модифицированный орган функции ниже согласуется с single AVL rotation with right child реализованным Mark Allen Weiss, упомянутым выше. Поскольку исходное сообщение не имеет переменной высоты, код ниже также не является.

//
// The 'root' variable is passed as a pointer by reference
//
void AVLTree::RotateLeft(Node* & root)
{
    //
    // This works as long as the GetRight() method returns a pointer, not a Node copy
    //
    Node *pB = root->GetRight();

    //
    // In the example values for three nodes, the root->right will become nullptr
    //
    root->SetRight(pB->GetLeft());

    //
    // In the example values, the pB->left will point to the node with value of 3
    //
    pB->SetLeft(root);

    //
    // Move root to point to where pB does (root->right)
    //
    root = pB;
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню