Implementation of AVL Tree using graphics in C++

AVL Trees are self-balancing Binary Search Trees where the difference between heights of left and right subtrees cannot be more than one for all nodes. Below is the example of the AVL Tree:
In this article, we will be implementing the concept of AVL Tree using graphics in C++. As a prerequisite, one must set up graphics. h in their editor. Use this link to install graphics.h in CodeBlocks.Â
Following are functionalities that will be illustrated in this article:
- Dynamic Insertion
- Displaying Tree structure (2D printing in the output window and graphical display)
- AVL Rotations
- Inorder, Preorder and Postorder traversals.
- The code accepts only integer values and hence includes functions to throw an error message when the user inputs invalid values.
Examples:
Input: 500, 400, 200, 150, 100, 700, 650, 600, 900, 450, 550, 50, 20, 800
Output:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 900
                      Â
                800
                     700
           650
                600
                     550
 Root -> 500
                     450
                400
                     200
           150
                     100
                50
                     20
                                     Â
Preorder: 500 Â 200 Â 100 Â 50 Â 20 Â 150 Â 400 Â 450 Â 650 Â 600 Â 550 Â 800 Â 700 Â 900
Inorder: 20 Â 50 Â 100 Â 150 Â 200 Â 400 Â 450 Â 500 Â 550 Â 600 Â 650 Â 700 Â 800 Â 900
Postorder: 20 Â 100 Â 50 Â 200 Â 450 Â 400 Â 150 Â 550 Â 600 Â 700 Â 900 Â 800 Â 650 Â 500
Below is the implementation and execution of a self-balancing BST using AVL rotations in graphics:
C++
// C++ program for the implementation// and execution of a self-balancing// BST using rotations and graphicsÂ
#include <algorithm>#include <bits/stdc++.h>#include <cstdio>#include <graphics.h>#include <iostream>#include <sstream>#include <string>using namespace std;Â
#define pow2(n) (1 << (n))const int x = 600;const int y = 100;Â
// Node Declarationstruct avl_node {Â Â Â Â int data;Â Â Â Â int height;Â Â Â Â struct avl_node* left;Â Â Â Â struct avl_node* right;Â
} * root, *temp1;Â
// Class Declarationclass avlTree {public:Â Â Â Â int height(avl_node*);Â Â Â Â int diff(avl_node*);Â Â Â Â avl_node* rr_rotation(avl_node*);Â Â Â Â avl_node* ll_rotation(avl_node*);Â Â Â Â avl_node* lr_rotation(avl_node*);Â Â Â Â avl_node* rl_rotation(avl_node*);Â Â Â Â avl_node* balance(avl_node*);Â Â Â Â avl_node* balanceTree(avl_node*);Â Â Â Â avl_node* insert(avl_node*, int);Â Â Â Â void display(avl_node*, int);Â Â Â Â void drawNode(avl_node*, int, int, int);Â Â Â Â void drawTree(avl_node*, int, int);Â Â Â Â void inorder(avl_node*);Â Â Â Â void preorder(avl_node*);Â Â Â Â void postorder(avl_node*);Â Â Â Â int validate(string s);Â Â Â Â bool checkInput(string s);Â Â Â Â avlTree()Â Â Â Â {Â Â Â Â Â Â Â Â root = NULL;Â Â Â Â Â Â Â Â temp1 = NULL;Â Â Â Â }};Â
// Driver Codeint main(){Â Â Â Â int choice, item, bf;Â Â Â Â int c;Â Â Â Â string str;Â Â Â Â avlTree avl;Â
    // Graphics    int gd = DETECT;    int gm;    initwindow(1200, 700, "AVL Tree Graphics",               0, 0, false, true);Â
    cout << "\n---------------------"         << endl;    cout << "AVL Tree Implementation"         << endl;    cout << "\n---------------------"         << endl;    cout << "1.Insert Element into the tree"         << endl;    cout << "3.Balance Tree"         << endl;    cout << "4.PreOrder traversal"         << endl;    cout << "5.InOrder traversal"         << endl;    cout << "6.PostOrder traversal"         << endl;    cout << "7.Exit" << endl;Â
    while (1) {        cout << "\nEnter your Choice: ";        cin >> choice;        switch (choice) {        case 1:Â
            // Accept input as string            cout << "Enter the value "                 << "to be inserted: ";            cin >> str;Â
            // Function call to check            // if input is valid or not            c = avl.validate(str);Â
            if (c == 100) {                item = std::stoi(                    str);                root = avl.insert(root, item);                cleardevice();                settextstyle(10, HORIZ_DIR, 3);                if (root == NULL) {                    cout << "Tree is Empty"                         << endl;                    outtextxy(400, 10,                              "Tree is Empty");                }Â
                outtextxy(10, 50,                          "Before Rotation : ");                avl.drawTree(root, x, y);            }            else                cout << "\n\t\tInvalid Input!"                     << endl;Â
            break;        case 2:Â
            // Tree structure in            // the graphics window            if (root == NULL) {                cout << "Tree is Empty"                     << endl;            }            avl.display(root, 1);            cleardevice();            avl.drawTree(root, x, y);Â
            break;        case 3:Â
            // Balance Tree            root = avl.balanceTree(root);Â
            cleardevice();            settextstyle(                10, HORIZ_DIR, 3);            outtextxy(10, 50,                      "After Rotation : ");            avl.drawTree(root, x, y);Â
            break;        case 4:            cout << "Preorder Traversal : ";            avl.preorder(root);            cout << endl;            break;        case 5:            cout << "Inorder Traversal:"                 << endl;            avl.inorder(root);            cout << endl;            break;        case 6:            cout << "Postorder Traversal:"                 << endl;            avl.postorder(root);            cout << endl;            break;        case 7:            exit(1);            break;        default:            cout << "Wrong Choice"                 << endl;        }    }    getch();    closegraph();    return 0;}Â
// Function to find the height// of the AVL Treeint avlTree::height(avl_node* temp){Â Â Â Â int h = 0;Â Â Â Â if (temp != NULL) {Â Â Â Â Â Â Â Â int l_height = height(temp->left);Â Â Â Â Â Â Â Â int r_height = height(temp->right);Â Â Â Â Â Â Â Â int max_height = max(l_height, r_height);Â Â Â Â Â Â Â Â h = max_height + 1;Â Â Â Â }Â Â Â Â return h;}Â
// Function to find the difference// between the left and the right// height of any node of the treeint avlTree::diff(avl_node* temp){Â Â Â Â int l_height = height(temp->left);Â Â Â Â int r_height = height(temp->right);Â Â Â Â int b_factor = l_height - r_height;Â
    return b_factor;}Â
// Function to perform the Right// Right Rotationavl_node* avlTree::rr_rotation(Â Â Â Â avl_node* parent){Â Â Â Â avl_node* temp;Â Â Â Â temp = parent->right;Â Â Â Â parent->right = temp->left;Â
    temp->left = parent;Â
    return temp;}Â
// Function to perform the Left// Left Rotationavl_node* avlTree::ll_rotation(Â Â Â Â avl_node* parent){Â
    avl_node* temp;    temp = parent->left;    parent->left = temp->right;    temp->right = parent;Â
    return temp;}Â
// Function to perform the Left// Right Rotationavl_node* avlTree::lr_rotation(Â Â Â Â avl_node* parent){Â Â Â Â avl_node* temp;Â Â Â Â temp = parent->left;Â Â Â Â parent->left = rr_rotation(temp);Â Â Â Â return ll_rotation(parent);}Â
// Function to perform the Right// Left Rotationavl_node* avlTree::rl_rotation(Â Â Â Â avl_node* parent){Â Â Â Â avl_node* temp;Â Â Â Â temp = parent->right;Â Â Â Â parent->right = ll_rotation(temp);Â Â Â Â return rr_rotation(parent);}Â
// Function to balance the treeavl_node* avlTree::balance(avl_node* temp){Â Â Â Â int bal_factor = diff(temp);Â
    if (bal_factor > 1) {        if (diff(temp->left) > 0) {Â
            temp = ll_rotation(temp);        }Â
        else {            temp = lr_rotation(temp);        }    }    else if (bal_factor < -1) {        if (diff(temp->right) > 0) {            temp = rl_rotation(temp);        }Â
        elseÂ
        {            temp = rr_rotation(temp);        }    }Â
    return temp;}Â
// Function to display the AVL Treevoid avlTree::display(avl_node* ptr, int level){Â Â Â Â int i;Â Â Â Â if (ptr != NULL) {Â Â Â Â Â Â Â Â display(ptr->right, level + 1);Â Â Â Â Â Â Â Â printf("\n");Â Â Â Â Â Â Â Â if (ptr == root)Â Â Â Â Â Â Â Â Â Â Â Â cout << "Root -> ";Â Â Â Â Â Â Â Â for (i = 0; i < level && ptr != root; i++) {Â
            cout << "       ";        }        int j;Â
        cout << ptr->data;        display(ptr->left, level + 1);    }}Â
// Function to balance the treeavl_node* avlTree::balanceTree(avl_node* root){Â Â Â Â int choice;Â Â Â Â if (root == NULL) {Â Â Â Â Â Â Â Â return NULL;Â Â Â Â }Â
    root->left = balanceTree(root->left);Â
    root->right = balanceTree(root->right);Â
    root = balance(root);    return root;}Â
// Function to create the node// int the AVL treevoid avlTree::drawNode(avl_node* root,                       int x, int y,                       int noderatio){    int bf = diff(root);    if (bf > 1 || bf < -1) {        setcolor(12);        outtextxy(600, 10, "Imbalanced!");        circle(x, y, 25);        setfillstyle(SOLID_FILL, 12);    }    else if (bf == 1 || bf == -1) {        setcolor(14);        circle(x, y, 25);        setfillstyle(SOLID_FILL, 14);        floodfill(x, y, YELLOW);    }    else {        setcolor(15);        circle(x, y, 25);        setfillstyle(SOLID_FILL, 15);        floodfill(x, y, WHITE);    }Â
    char arr[5];    itoa(root->data, arr, 10);    outtextxy(x, y, arr);Â
    if (root->left != NULL) {        line(x, y, x - 20 * noderatio, y + 70);        drawNode(root->left, x - 20 * noderatio, y + 70,                 noderatio - 2);    }    if (root->right != NULL) {        line(x, y, x + 20 * noderatio, y + 70);        drawNode(root->right, x + 20 * noderatio, y + 70,                 noderatio - 2);    }}Â
// Function to draw the AVL treevoid avlTree::drawTree(avl_node* root, int x, int y){Â Â Â Â settextstyle(10, HORIZ_DIR, 3);Â Â Â Â outtextxy(10, 10, "Tree");Â Â Â Â outtextxy(20, 600, "Balanced : ");Â Â Â Â circle(190, 605, 10);Â
    // Floodfill(190, 605, WHITE);    outtextxy(520, 600, "L/R Heavy : ");    setcolor(14);    circle(700, 605, 10);Â
    // Floodfill(700, 605, YELLOW);    setcolor(15);    outtextxy(950, 600, "Critical : ");    setcolor(12);    circle(1115, 605, 10);Â
    // Floodfill(1115, 605, RED);Â
    settextstyle(10, HORIZ_DIR, 2);    drawNode(root, x, y, 8);}Â
// Function to insert element// in the treeavl_node* avlTree::insert(Â Â Â Â avl_node* root, int value){Â
    if (root == NULL) {        root = new avl_node;        root->data = value;        root->left = NULL;        root->right = NULL;Â
        return root;    }Â
    if (value < root->data) {        root->left = insert(            root->left, value);    }Â
    else if (value > root->data) {        root->right = insert(            root->right, value);    }    else        cout << "\n\tValue already"             << " exists!" << endl;Â
    return root;}Â
// Function to perform the Inorder// Traversal of AVL Treevoid avlTree::inorder(avl_node* root){Â Â Â Â if (root == NULL)Â Â Â Â Â Â Â Â return;Â Â Â Â inorder(root->left);Â Â Â Â cout << root->data << "Â ";Â
    inorder(root->right);}Â
// Function to perform the Preorder// Traversal of AVL Treevoid avlTree::preorder(avl_node* root){Â Â Â Â if (root == NULL)Â Â Â Â Â Â Â Â return;Â
    cout << root->data << " ";    preorder(root->left);    preorder(root->right);}Â
// Function to perform the Postorder// Traversal of AVL Treevoid avlTree::postorder(avl_node* root){Â Â Â Â if (root == NULL)Â Â Â Â Â Â Â Â return;Â Â Â Â postorder(root->left);Â Â Â Â postorder(root->right);Â Â Â Â cout << root->data << "Â ";}Â
// Function to check the input// validationbool avlTree::checkInput(string str){Â Â Â Â for (int i = 0; i < str.length(); i++)Â Â Â Â Â Â Â Â if (isdigit(str[i]) == false)Â Â Â Â Â Â Â Â Â Â Â Â return false;Â Â Â Â return true;}Â
// Function to validate AVL Treeint avlTree::validate(string str){    if (checkInput(str))        return 100;    else        return 10;} |
Â
Â
Output:
Â
Â
Â
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!




