c++algorithmtreeavl-tree

My ALV Tree balance factors calculate incorrectly


Why is my output incorrect? Code should print balance factors in range {-1, 0, 1}, but i get: 0 255 0 -255 -255 -255 0 -1 0 0 0 254. When I set height of nullptr nodes to 0 tree calculates correctly but balance factors calculate incorrectly. I do not really understand where is my mistake. Seems like code should work correctly, but it is not.

#include "iostream"
#include <string>

using namespace std;

class AVL_Tree{
private:
    struct node{
        int key;
        unsigned char height;
        node* left;
        node* right;
        node(int k){
            key = k;
            left = right = nullptr;
            height = 0;
        }
    };

    unsigned char height(node* p){
        return p?p->height:(-1);
    }

    void fixheight(node* p){
        unsigned char hl = height(p->left);
        unsigned char hr = height(p->right);
        p->height = (hl>hr ? hl : hr) + 1;
    }

    node* rotateright(node* p){
        node* q = p->left;
        p->left = q->right;
        q->right = p;
        fixheight(p);
        fixheight(q);
        return q;
    }

    node* rotateleft(node* q) // левый поворот вокруг q
    {
        node* p = q->right;
        q->right = p->left;
        p->left = q;
        fixheight(q);
        fixheight(p);
        return p;
    }

    node* balance(node* p){
        fixheight(p);
        if (balancefactor(p) == 2){
            if (balancefactor(p->right) < 0){
                p->right = rotateright(p->right);
            }
            return rotateleft(p);
        }
        if (balancefactor(p) == -2){
            if (balancefactor(p->left) > 0){
                p->left = rotateleft(p->left);
            }
            return rotateright(p);
        }
        return p;
    }

    node* insert(node* p, int k) // вставка ключа k в дерево с корнем p
    {
        if( !p ) return new node(k);
        if( k<p->key )
            p->left = insert(p->left,k);
        else
            p->right = insert(p->right,k);
        return balance(p);
    }
    void printfactors(node* curr){
        if (curr){
            printfactors(curr->left);
            cout << balancefactor(curr) << " ";
            printfactors(curr->right);
        }
    }
    int balancefactor(node* p){
        return height(p->right) - height(p->left);
    }

    node* root;
public:

    AVL_Tree(int x){
        root = new node(x);
    }

    void insert(int k){
        root = insert(root, k);
    }

    void printfactors(){
        printfactors(root);
    }
};

int main(){
    srand(time(nullptr));
    int a = rand() % 101;
    AVL_Tree tree(20);
    tree.insert(10);
    tree.insert(11);
    tree.insert(12);
    tree.insert(5);
    tree.insert(3);
    tree.insert(15);
    tree.insert(18);
    tree.insert(25);
    tree.insert(23);
    tree.insert(24);
    tree.insert(22);

    tree.printfactors();

    return 0;
}

Solution

  • The main problem is the return type of your height function: it is set to unsigned char, but it can return -1, which will be interpreted as 255.

    Change that return type to just char.

    Another potential issue is that a rotation may affect the balance factor of the parent of the node that is rotated. So at several places in your code you should call fixheight on such parent nodes.