Понимание факторов баланса / высоты узла для вращений AVL

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

http://i.imgur.com/yh5zNIl.png

Может кто-нибудь объяснить мне, как мы на самом деле находим фактор баланса для каждого узла?

Я знаю, что если высота [(левое поддерево) - (правое поддерево)] не находится в пределах (-1<= x <= 1), то она не сбалансирована... но я не могу понять, как найти "x".

(редактировать: мне не нужен код, я просто хочу понять, как найти BF).

4 ответа

Коэффициент баланса узла - это разница высоты его левого и правого узлов-потомков.

Коэффициент баланса определяется некоторыми как: balance = node.left.height - node.right.height

и другими как: баланс = узел.райт.хайт - узел.лефт.хайт

поэтому, если вы хотите понять баланс некоторых узлов на графике, вы должны знать, как они определяют коэффициент баланса.

Например, википедия определяет его как node.left.height - node.right.height, и вы можете видеть, что результаты формулы соответствуют коэффициентам баланса узлов Avl Tree Balance of Nodes Пример

X - высота левого поддерева - высота правого поддерева.

Если у левого поддерева максимальная высота равна трем, а у правого поддерева максимальная высота равна двум, тогда коэффициент баланса будет

3 - 2 = Balance Factor of 1 (Left Heavy)

Наоборот:

2 - 3 = Balance Factor of -1 (Right Heavy)

Если оба одинаковы:

3 - 3 = Balance Factor of 0 (Even Heavy)

Дерево становится несбалансированным, когда разница высот больше 1 или меньше -1.

5 - 3 = Balance Factor of 2 (UNBALANCED!)
3 - 5 = Balance Factor of -2 (UNBALANCED!)

Если я правильно понимаю ваш вопрос, вы хотите знать, как поддерживать баланс-фактор данного узла. Лучший способ сохранить трек - это сделать "вставку" в дерево. Это потому, что вы знаете, идет ли ваш новый узел слева или справа от "текущего" узла. Когда он идет влево, вы уменьшаете баланс, а когда он идет вправо, вы увеличиваете баланс. Идея состоит в том, чтобы дерево уже было сбалансировано до выхода из метода "insert".

Другой подход, который я видел, НЕ выполняет балансировку во время "вставки". Вы просто вставляете, как в BST. После вставки вы начинаете действие балансировки, где вы получаете левое поддерево и высоту правого поддерева в каждом узле и начинаете перетасовывать указатели. Это не очень хороший подход, так как вы берете O(logn) для каждого узла при поиске высоты, и поскольку вы делаете это для каждого узла, это приводит к n*O(logn).

Я публикую метод "вставки", который я когда-то написал, который поддерживает сбалансированное дерево при каждой вставке и НЕ вычисляет высоту отдельно в любой точке во время вставки. Посмотрите, поможет ли это:

Node*
AVL::insert(Node* node, int key, int value)
{
    if(node == NULL)
        node = new Node(key, value);

    else if (key <= node->key)
    {
        node->balance--;
        node->left = insert(node->left, key, value);
    }

    else if (key > node->key)
    {
        node->balance++;
        node->right = insert(node->right, key, value);  
    }

    // Right Tree Heavy
    if (node->balance == 2) 
    { 
        // Left tree unbalanced
        if (node->right && node->right->balance == 1) 
        {
            // LL
            node = singleLeftRotation(node);
            node->balance = 0;
            node->left->balance = 0;
        }
        if (node->right && node->right->balance == -1) 
        {
            // LR
            int nodeRLBalance = node->right->left->balance;
            node = doubleLeftRotation(node);
            node->balance = 0;
            node->left->balance = nodeRLBalance == 1 ? -1 : 0;
            node->right->balance = nodeRLBalance == -1 ? 1 : 0;
        }
    }

    // Left Tree Heavy
    if (node->balance == -2) 
    {
        // Right tree unbalanced
        if (node->left && node->left->balance == -1) 
        {
            // RR
            node = singleRightRotation(node);
            node->balance = 0;
            node->right->balance = 0;
        }
        if (node->left && node->left->balance == 1) 
        {
            // RL
            int nodeLRBalance = node->left->right->balance;
            node = doubleRightRotation(node);
            node->balance = 0;
            node->left->balance = nodeLRBalance == 1 ? -1 : 0;
            node->right->balance = nodeLRBalance == -1 ? 1 : 0;
        }
    }

    return node;
}

это изображение, вероятно, поможет вам. Несбалансированное дерево AVL имеет нарушение в E-узле

несбалансированное дерево AVL

Другие вопросы по тегам