Ошибка двойного вращения дерева AVL

Я работаю над проектом для школы, который включает в себя реализацию дерева AVL с использованием итеративной функции вставки, и у меня возникла проблема.

Я не уверен на 100%, что я не делаю, но моя программа не дает правильного вывода.

Вот что у меня есть для моей функции вставки:

bool AVLTree::insert(string ss, string na){

AVLNode* newNode = new AVLNode(ss, na);
updateHeight(newNode);

//Tree is empty, make the new Node the root of a new tree
if(getRoot() == nullptr){
    root = newNode;
    print();
    return true;
}
//Tree is not empty
else{
    AVLNode* checkPoint;
    checkPoint = root;

    while(checkPoint != nullptr){

        //If the ssn is already in the tree
        if(checkPoint->ssn.compare(newNode->ssn) == 0){
            return false;
        }
        else if(checkPoint->ssn.compare(newNode->ssn) > 0){
            if(checkPoint->left == nullptr){
                break;
            }
            checkPoint = checkPoint->left;
        }
        else{
            if(checkPoint->right == nullptr){
                break;
            }
            checkPoint = checkPoint->right;
        }
    }

    if(newNode->ssn.compare(checkPoint->ssn) < 0){
        checkPoint->left = newNode;
    }
    else{
        checkPoint->right = newNode;
    }
    updateHeight(checkPoint);
    balance(root);
    print();
    return true;
}

Это моя функция, которую я придумал до сих пор, для моего проекта мне предоставили функцию баланса и updateHeight, которую я предоставлю здесь:

AVLNode* AVLTree::balance(AVLNode* node){
updateHeight(node);
if (balanceFactor(node) == 2) {
    if (balanceFactor(node->left) < 0) {
        node->left = rotateLeft(node->left); // for left right case
    }

    AVLNode* temp = rotateRight(node);
    updateHeight(temp);
    return temp;
}

if (balanceFactor(node) == -2) {
    if (balanceFactor(node->right) > 0) {
        node->right = rotateRight(node->right);  // for right left case
    }
    AVLNode* temp2 = rotateLeft(node);
    updateHeight(temp2);
    return temp2;
}
return node;

И для высоты обновления:

void AVLTree::updateHeight(AVLNode* node){
    int hl = height(node->left);
    int hr = height(node->right);
    node->height = (hl>hr ? hl : hr) + 1;
}

В основном моей задачей было реализовать функции вставки и удаления. Мой ввод для дерева avl в следующем порядке:

5, 8, 9, 3, 6, 7, 5

и мой вывод таков:

      8
     / \
    5   9
   / \
  3   6
 /     \
2       7

когда должно быть:

        6
     /     \
    3       8
   / \     / \
  2   5   7   9

Возвращаясь к моей функции вставки, я считаю, что проблема заключается в том, что я неправильно обновляю высоту каждый раз, когда вставляю узел. Программа отлично справляется с одинарными вращениями, но с двойными вращениями не работает. Любая помощь будет оценена по достоинству.


person Geedubs123    schedule 11.05.2016    source источник


Ответы (1)


Вы должны проверить и сбалансировать все уровни дерева выше точки вставки узла.

person GMichael    schedule 11.05.2016
comment
Хорошо, это имеет смысл, но как мне это сделать, следует ли мне начать с нового узла и подняться вверх или попытаться спуститься от корня и сбалансировать все дерево? - person Geedubs123; 11.05.2016
comment
Я обычно реализую insert как рекурсивную функцию, и когда она существует в узле, она перебалансирует все поддерево ниже текущего узла. - person GMichael; 11.05.2016
comment
да, везде я вижу в Интернете все это рекурсивную реализацию. к сожалению, мой профессор дал нам требование сделать это нерекурсивным способом. Пока мои попытки сделать это с тех пор, как вы сказали, не увенчались успехом. Однако, по крайней мере, у меня есть представление о том, что мне нужно делать дальше, спасибо. - person Geedubs123; 11.05.2016
comment
Вы можете реализовать рекурсию вручную. Храните узлы, которые проходит алгоритм, в стеке (можно реализовать с помощью массива) и выполняйте итерацию по стеку при возврате из функции. Будет два цикла: один для вставки (может иметь никнейм i++) и другой для баланса (никнейм --i) - person GMichael; 11.05.2016
comment
нет, подожди, чувак, я понял, я тупой, я забыл подключить newNode к контрольной точке, возвращаясь назад, то есть мне пришлось добавить: newNode-›parent = checkPoint - person Geedubs123; 11.05.2016