An AVL tree is a binary search tree(BST) however, unlike binary search trees, an AVL tree (named after Georgy Adelson-Velsky and Evgenii Landis) is self balancing. So no matter how many nodes you insert into the tree, it will adjust it’s branches and ensure the tree is balanced at all times. Making sure the subtree heights only differ by at most 1. BSTs are great for segregating and storing data with a O(log n) search time. Downside with BST is that it can get weighted on one side and doesn’t have an restrictions to prevent it from getting skewed. By switching to an AVL, data is balanced in the tree and the search time is decreased to log n.
So it is more efficient in most cases to use the AVL tree, below is an example of how to code this in C++. Note that the AVL tree uses a lot of the same code the BST did from this post.
#pragma once #include <iomanip> #include <iostream> using namespace std; class AVL { public: AVL(){ root = nullptr; } ~AVL(){ destroy(root); } //My Node class for storing data, note how I add height struct Node{ int data; Node *left; Node *right; int height; Node(int d){ data = d; left = nullptr; right = nullptr; height = 0; } void updateHeight(){ int lHeight = 0; int rHeight = 0; if (left != nullptr) { lHeight = left->height; } if (right != nullptr) { rHeight = right->height; } int max = (lHeight > rHeight) ? lHeight : rHeight; height = max + 1; } }; void insert(int val){ insert(val, root); } //Rotate a Node branch to the left, in order to balance things Node* rotateLeft(Node *&leaf){ Node* temp = leaf->right; leaf->right = temp->left; temp->left = leaf; //update the Nodes new height leaf->updateHeight(); return temp; } //Rotate a Node branch to the right, in order to balance things Node* rotateRight(Node *&leaf){ Node* temp = leaf->left; leaf->left = temp->right; temp->right = leaf; //update the Nodes new height leaf->updateHeight(); return temp; } //Rotate a Node branch to the right then the left, in order to balance things Node* rotateRightLeft(Node *&leaf){ Node* temp = leaf->right; leaf->right = rotateRight(temp); return rotateLeft(leaf); } //Rotate a Node branch to the left then the right, in order to balance things Node* rotateLeftRight(Node *&leaf){ Node* temp = leaf->left; leaf->left = rotateLeft(temp); return rotateRight(leaf); } //Function that checks each Node's left and right branches to determine if they are unbalanced //If they are, we rotate the branches void rebalance(Node *&leaf){ int hDiff = getDiff(leaf); if (hDiff > 1){ if (getDiff(leaf->left) > 0) { leaf = rotateRight(leaf); } else { leaf = rotateLeftRight(leaf); } } else if(hDiff < -1) { if (getDiff(leaf->right) < 0) { leaf = rotateLeft(leaf); } else { leaf = rotateRightLeft(leaf); } } } private: Node *root; //Insert a Node (very similar to BST, except we need to update Node height and then check for rebalance) void insert(int d, Node *&leaf){ if (leaf == nullptr){ leaf = new Node(d); leaf->updateHeight(); } else { if (d < leaf->data){ insert(d, leaf->left); leaf->updateHeight(); rebalance(leaf); } else{ insert(d, leaf->right); leaf->updateHeight(); rebalance(leaf); } } } //Same as BST void destroy(Node *&leaf){ if (leaf != nullptr){ destroy(leaf->left); destroy(leaf->right); delete leaf; } } //Get the difference between Node right and left branch heights, if it returns positive //We know the left side is greater, if negative, we know the right side is greater int getDiff(Node *leaf){ int lHeight = 0; int rHeight = 0; if (leaf->left != nullptr) { lHeight = leaf->left->height; } if (leaf->right != nullptr) { rHeight = leaf->right->height } return lHeight - rHeight; } };
Let me know if you have any issues!
Hello! I am new to C++ and I am unsure of a couple of things.
Its my first time encountering the data structure Node*& . What does this mean and how does it differ from Node*? Is there any special cases where Node*& must be used?
I am also confused on how to implement this program in the int main(). Am I supposed to implement it by using avl.insert(value)? Or is there another way to call upon the function.
Sorry for all these questions and thank you for your help!
Hey Leia, so breaking this down, Node is my class that I am using to represent a point and its data on the AVL tree. Whenever you use ‘*’ in C++ it is indicating a pointer and ‘&’ is a reference to an item’s address. So together, I am taking a pointer parameter by reference on the Node class object. Basically, I am doing this to dereference the reference to get the originally value of the Node. This article is pretty helpful in explaining pointers and references in general, http://www.dev-hq.net/c++/12–pointers-and-references.
So in your main, you need to first call the constructor to create your tree, so that the tree gets initiated. You can do something along the lines of “AVL myTree;”. Once created, you can then insert values, “myTree.insert(value)”. Make sense?
Let me know if you need anymore help!
Can you find an easiest way to delete one node in the tree?