BS Computer Science

  • Home
  • Download
  • Premium Version
  • Custom Theme
  • Contact
    • download templates
    • Link 2
    • Link 3

 


AVL Tree:

An AVL tree defined as a self-balancing  (BST) where the difference between heights of left and right subtrees for any node cannot be more than one.

The difference between the heights of the left subtree and the right subtree for any node is known as the balance factor of the node.

Example of AVL Trees:


The above tree is AVL because the differences between the heights of left and right subtrees for every node are less than or equal to 1.

Operations on an AVL Tree:

Insertion
deletion
searching

·    

Rotating the subtrees in an AVL Tree:

An AVL tree may rotate in one of the following four ways to keep itself balanced:

Left Rotation:

When a node is added into the right subtree of the right subtree, if the tree gets out of balance, we do a single left rotation.


Right Rotation:

If a node is added to the left subtree of the left subtree, the AVL tree may get out of balance, we do a single right rotation.


Left-Right Rotation:

A left-right rotation is a combination in which first left rotation takes place after that right rotation executes.


Right-Left Rotation:

A right-left rotation is a combination in which first right rotation takes place after that left rotation executes.


Applications of AVL Tree:

It is used to index huge records in a database and also to efficiently search in that.

·         For all types of in-memory collections, including sets and dictionaries, AVL Trees are used.

·         Database applications, where insertions and deletions are less common but frequent data lookups are necessary

·         Software that needs optimized search.

·         It is applied in corporate areas and storyline games.

Advantages of AVL Tree:

·         AVL trees can self-balance themselves.

·         It is surely not skewed.

·         It provides faster lookups than Red-Black Trees

·         Better searching time complexity compared to other trees like binary tree.

·         Height cannot exceed log(N), where, N is the total number of nodes in the tree.

Disadvantages of AVL Tree:

·         It is difficult to implement.

·         It has high constant factors for some of the operations.

·         Less used compared to Red-Black trees.

·         Due to its rather strict balance, AVL trees provide complicated insertion and removal operations as more rotations are performed.

·         Take more processing for balancing.

 

 

Program

#include <bits/stdc++.h>

using namespace std;

 

// AVL tree node

struct AVLwithparent {

    struct AVLwithparent* left;

    struct AVLwithparent* right;

    int key;

    struct AVLwithparent* par;

    int height;

};

 

// Function to update the height of

// a node according to its children's

// node's heights

void Updateheight(

    struct AVLwithparent* root)

{

    if (root != NULL) {

 

        // Store the height of the

        // current node

        int val = 1;

 

        // Store the height of the left

        // and right subtree

        if (root->left != NULL)

            val = root->left->height + 1;

 

        if (root->right != NULL)

            val = max(

                val, root->right->height + 1);

 

        // Update the height of the

        // current node

        root->height = val;

    }

}

 

// Function to handle Left Left Case

struct AVLwithparent* LLR(

    struct AVLwithparent* root)

{

    // Create a reference to the

    // left child

    struct AVLwithparent* tmpnode = root->left;

 

    // Update the left child of the

    // root to the right child of the

    // current left child of the root

    root->left = tmpnode->right;

 

    // Update parent pointer of the

    // left child of the root node

    if (tmpnode->right != NULL)

        tmpnode->right->par = root;

 

    // Update the right child of

    // tmpnode to root

    tmpnode->right = root;

 

    // Update parent pointer of

    // the tmpnode

    tmpnode->par = root->par;

 

    // Update the parent pointer

    // of the root

    root->par = tmpnode;

 

    // Update tmpnode as the left or the

    // right child of its parent pointer

    // according to its key value

    if (tmpnode->par != NULL

        && root->key <tmpnode->par->key) {

        tmpnode->par->left = tmpnode;

    }

    else {

        if (tmpnode->par != NULL)

            tmpnode->par->right = tmpnode;

    }

 

    // Make tmpnode as the new root

    root = tmpnode;

 

    // Update the heights

    Updateheight(root->left);

    Updateheight(root->right);

    Updateheight(root);

    Updateheight(root->par);

 

    // Return the root node

    return root;

}

 

// Function to handle Right Right Case

struct AVLwithparent* RRR(

    struct AVLwithparent* root)

{

    // Create a reference to the

    // right child

    struct AVLwithparent* tmpnode = root->right;

 

    // Update the right child of the

    // root as the left child of the

    // current right child of the root

    root->right = tmpnode->left;

 

    // Update parent pointer of the

    // right child of the root node

    if (tmpnode->left != NULL)

        tmpnode->left->par = root;

 

    // Update the left child of the

    // tmpnode to root

    tmpnode->left = root;

 

    // Update parent pointer of

    // the tmpnode

    tmpnode->par = root->par;

 

    // Update the parent pointer

    // of the root

    root->par = tmpnode;

 

    // Update tmpnode as the left or

    // the right child of its parent

    // pointer according to its key value

    if (tmpnode->par != NULL

        && root->key <tmpnode->par->key) {

        tmpnode->par->left = tmpnode;

    }

    else {

        if (tmpnode->par != NULL)

            tmpnode->par->right = tmpnode;

    }

 

    // Make tmpnode as the new root

    root = tmpnode;

 

    // Update the heights

    Updateheight(root->left);

    Updateheight(root->right);

    Updateheight(root);

    Updateheight(root->par);

 

    // Return the root node

    return root;

}

 

// Function to handle Left Right Case

struct AVLwithparent* LRR(

    struct AVLwithparent* root)

{

    root->left = RRR(root->left);

    return LLR(root);

}

 

// Function to handle right left case

struct AVLwithparent* RLR(

    struct AVLwithparent* root)

{

    root->right = LLR(root->right);

    return RRR(root);

}

 

// Function to insert a node in

// the AVL tree

struct AVLwithparent* Insert(

    struct AVLwithparent* root,

    struct AVLwithparent* parent,

    int key)

{

 

    if (root == NULL) {

 

        // Create and assign values

        // to a new node

        root = new struct AVLwithparent;

 

        // If the root is NULL

        if (root == NULL) {

            cout<< "Error in memory"

                 <<endl;

        }

 

        // Otherwise

        else {

            root->height = 1;

            root->left = NULL;

            root->right = NULL;

            root->par = parent;

            root->key = key;

        }

    }

 

    else if (root->key > key) {

 

        // Recur to the left subtree

        // to insert the node

        root->left = Insert(root->left,

                            root, key);

 

        // Store the heights of the

        // left and right subtree

        int firstheight = 0;

        int secondheight = 0;

 

        if (root->left != NULL)

            firstheight = root->left->height;

 

        if (root->right != NULL)

            secondheight = root->right->height;

 

        // Balance the tree if the

        // current node is not balanced

        if (abs(firstheight

                - secondheight)

            == 2) {

 

            if (root->left != NULL

                && key < root->left->key) {

 

                // Left Left Case

                root = LLR(root);

            }

            else {

 

                // Left Right Case

                root = LRR(root);

            }

        }

    }

 

    else if (root->key < key) {

 

        // Recur to the right subtree

        // to insert the node

        root->right = Insert(root->right,

                             root, key);

 

        // Store the heights of the

        // left and right subtree

        int firstheight = 0;

        int secondheight = 0;

 

        if (root->left != NULL)

            firstheight

                = root->left->height;

 

        if (root->right != NULL)

            secondheight = root->right->height;

 

        // Balance the tree if the

        // current node is not balanced

        if (abs(firstheight - secondheight) == 2) {

            if (root->right != NULL

                && key < root->right->key) {

                // Right Left Case

                root = RLR(root);

            }

            else {

                // Right Right Case

                root = RRR(root);

            }

        }

    }

 

    // Case when given key is already

    // in the tree

    else {

    }

    // Update the height of the

    // root node

    Updateheight(root);

    // Return the root node

    return root;

}

// Function to print the preorder

// traversal of the AVL tree

void printpreorder(

    struct AVLwithparent* root)

{

    // Print the node's value along

    // with its parent value

    cout<< "Node: " << root->key

         << ", Parent Node: ";

    if (root->par != NULL)

        cout<< root->par->key <<endl;

    else

        cout<< "NULL" <<endl;

    // Recur to the left subtree

    if (root->left != NULL) {

        printpreorder(root->left);

    }

    // Recur to the right subtree

    if (root->right != NULL) {

        printpreorder(root->right);

    }

}

// Driver Code

int main()

{

    struct AVLwithparent* root;

    root = NULL;

    // Function Call to insert nodes

    root = Insert(root, NULL, 10);

    root = Insert(root, NULL, 20);

    root = Insert(root, NULL, 30);

    root = Insert(root, NULL, 40);

    root = Insert(root, NULL, 50);

    root = Insert(root, NULL, 25);

 

    // Function call to print the tree

    printpreorder(root);

}

Output:



 


Preorder Traversal:

At first visit the root then traverse left subtree and then traverse the right subtree.

Follow the below steps to implement the idea:

  • Visit the root and print the data.
  • Traverse left subtree
  • Traverse the right subtree

Program:

// C++ code to implement the approach

//Pre-Order

#include <bits/stdc++.h>

using namespace std;

// Class describing a node of tree

class Node {

public:

    int data;

    Node* left;

    Node* right;

    Node(int v)

    {

        this->data = v;

        this->left = this->right = NULL;

    }

};

// Preorder Traversal

void printPreOrder(Node* node)

{

    if (node == NULL)

        return;

 

    // Visit Node

    cout << node->data << " ";

 

    // Traverse left subtree

    printPreOrder(node->left);

 

    // Traverse right subtree

    printPreOrder(node->right);

}

// Driver code

int main()

{

    // Build the tree

    Node* root = new Node(100);

    root->left = new Node(20);

    root->right = new Node(200);

    root->left->left = new Node(10);

    root->left->right = new Node(30);

    root->right->left = new Node(150);

    root->right->right = new Node(300);

    // Function call

    cout << "Preorder Traversal: ";

    printPreOrder(root);

    return 0;

}

Output:



 

Postorder Traversal:

Below is the idea to solve the problem:

At first traverse left subtree then traverse the right subtree and then visit the root.

Follow the below steps to implement the idea:

  • Traverse left subtree
  • Traverse the right subtree
  • Visit the root and print the data.

Program:

#include <bits/stdc++.h>

using namespace std;

 

// Class to define structure of a node

class Node {

public:

    int data;

    Node* left;

    Node* right;

    Node(int v)

    {

        this->data = v;

        this->left = this->right = NULL;

    }

};

 

// PostOrder Traversal

void printPostOrder(Node* node)

{

    if (node == NULL)

        return;

 

    // Traverse left subtree

    printPostOrder(node->left);

 

    // Traverse right subtree

    printPostOrder(node->right);

 

    // Visit node

    cout << node->data << " ";

}

 

// Driver code

int main()

{

    Node* root = new Node(100);

    root->left = new Node(20);

    root->right = new Node(200);

    root->left->left = new Node(10);

    root->left->right = new Node(30);

    root->right->left = new Node(150);

    root->right->right = new Node(300);

 

    // Function call

    cout << "PostOrder Traversal: ";

    printPostOrder(root);

    cout << "\n";

 

    return 0;

}

 

Program:


 


 

 

Subscribe to: Comments ( Atom )

ABOUT AUTHOR

LATEST POSTS

  • Preorder & Postorder Traversal
      Preorder Traversal: At first visit the  root  then traverse  left subtree  and then traverse the  right subtree . Follow the below ste...
  • Introduction to BS Computer Science
     Introduction to BS Computer Science The BSCS (Bachelor of Science in Computer Science) is an undergraduate degree that lasts for four years...
  • BST
      Binary   Search Tree: A Binary Search Tree (BST) is a type of data structure that helps in organizing and managing data efficiently. Her...
  • Introduction to C++ Language
      Introduction to C++ Language C++ is a powerful, high-performance programming language widely used in software development. It is an extens...
  • Selection Sort
      Selection Sort: Selection sort is a simple and efficient sorting algorithm that works by repeatedly selecting the smallest (or largest)...
  • AVL Tree
      AVL Tree: An AVL tree defined as a self-balancing   (BST) where the difference between heights of left and right subtrees for any node c...
  • Radix sort
      Radix sort: Understanding Radix Sort: A Linear Sorting Algorithm Radix Sort is a fascinating and efficient sorting algorithm, especially...
  • Merge sort
      Merge sort:   Merge sort is a sorting technique based on divide and conquer technique. Merge sort first divides the array into equal hal...
  • Quick Sort
    Quick Sort QuickSort is a sorting algorithm based on the   Divide and Conquer algorithm  that picks an element as a pivot and partitions t...
  • Queue
      Queue: Introduction: Queue is an abstract data structure, somewhat similar to Stacks. Unlike stacks, a queue is open at both its ends....

Categories

BSCS

Instagram

 Templates Top Best Blogger

Latest Posts

  • Preorder & Postorder Traversal
  • Introduction to BS Computer Science
  • BST
  • Introduction to C++ Language
  • Selection Sort

Flickr

About

Copyright 2014 BS Computer Science .
Designed by OddThemes Shared by Way Templates