| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- #include "AVLCommand.h"
- // examples of AVL tree algorithms:
- // https://tfetimes.com/c-avl-tree/
- // https://stackoverflow.com/questions/29866315/class-for-avl-trees-c
- // http://www.sanfoundry.com/cpp-program-implement-avl-trees/
- // AVL explanation:
- // http://www.btechsmartclass.com/DS/U5_T2.html
- // combination of geeksforgeeks AVL insert and delete code
- // written for C
- // => convert into a C++ class
- // An AVL tree node struct that is probably useless to me
- struct Node { // already have a struct inside BST...
- // maybe no pointers in here...
- // but then why bother with a struct :/
- int key;
- //struct Node *left;
- //struct Node *right;
- int height;
- };
- // constructor: builds an AVL tree from BST tree bst
- AVLCommands::AVLCommands() {
- BST bst(); // initialize BST with root null and sized 0
- }
- void AVLCommands::Insert(int key) {
- // normal BST insertion
- bst.Insert(key);
- // update height of ancestor node
- // geeksforgeeks C:
- node->height = 1 + max(height(node->left),
- height(node->right));
- // check if the tree is unbalanced by checking
- // ancestor balance factor
- // if unbalanced
- // left-left
- // right-right
- // left-right
- // right-left
- }
- // Recursive function to insert key in subtree rooted
- // with node and returns new root of subtree.
- struct Node* insert(struct Node* node, int key)
- {
- /* 1. Perform the normal BST insertion */
- if (node == NULL)
- return(newNode(key));
- if (key < node->key)
- node->left = insert(node->left, key);
- else if (key > node->key)
- node->right = insert(node->right, key);
- else // Equal keys are not allowed in BST
- return node;
- /* 2. Update height of this ancestor node */
- node->height = 1 + max(height(node->left),
- height(node->right));
- /* 3. Get the balance factor of this ancestor
- node to check whether this node became
- unbalanced */
- int balance = getBalance(node);
- // If this node becomes unbalanced, then
- // there are 4 cases
- // Left Left Case
- if (balance > 1 && key < node->left->key)
- return rightRotate(node);
- // Right Right Case
- if (balance < -1 && key > node->right->key)
- return leftRotate(node);
- // Left Right Case
- if (balance > 1 && key > node->left->key)
- {
- node->left = leftRotate(node->left);
- return rightRotate(node);
- }
- // Right Left Case
- if (balance < -1 && key < node->right->key)
- {
- node->right = rightRotate(node->right);
- return leftRotate(node);
- }
- /* return the (unchanged) node pointer */
- return node;
- }
- // A utility function to get maximum of two integers
- int max(int a, int b);
- // A utility function to get height of the tree
- int height(struct Node *N) {
- if (N == NULL)
- return 0;
- return N->height;
- }
- // A utility function to get maximum of two integers
- int max(int a, int b) {
- return (a > b)? a : b;
- }
- /* Helper function that allocates a new node with the given key and
- NULL left and right pointers. */
- struct Node* newNode(int key)
- {
- struct Node* node = (struct Node*)
- malloc(sizeof(struct Node));
- node->key = key;
- node->left = NULL;
- node->right = NULL;
- node->height = 1; // new node is initially added at leaf
- return(node);
- }
- // A utility function to right rotate subtree rooted with y
- // See the diagram given above.
- struct Node *rightRotate(struct Node *y)
- {
- struct Node *x = y->left;
- struct Node *T2 = x->right;
- // Perform rotation
- x->right = y;
- y->left = T2;
- // Update heights
- y->height = max(height(y->left), height(y->right))+1;
- x->height = max(height(x->left), height(x->right))+1;
- // Return new root
- return x;
- }
- // A utility function to left rotate subtree rooted with x
- // See the diagram given above.
- struct Node *leftRotate(struct Node *x)
- {
- struct Node *y = x->right;
- struct Node *T2 = y->left;
- // Perform rotation
- y->left = x;
- x->right = T2;
- // Update heights
- x->height = max(height(x->left), height(x->right))+1;
- y->height = max(height(y->left), height(y->right))+1;
- // Return new root
- return y;
- }
- // Get Balance factor of node N
- int getBalance(struct Node *N)
- {
- if (N == NULL)
- return 0;
- return height(N->left) - height(N->right);
- }
- /* Given a non-empty binary search tree, return the
- node with minimum key value found in that tree.
- Note that the entire tree does not need to be
- searched. */
- struct Node * minValueNode(struct Node* node)
- {
- struct Node* current = node;
- /* loop down to find the leftmost leaf */
- while (current->left != NULL)
- current = current->left;
- return current;
- }
- // Recursive function to delete a node with given key
- // from subtree with given root. It returns root of
- // the modified subtree.
- struct Node* deleteNode(struct Node* root, int key)
- {
- // STEP 1: PERFORM STANDARD BST DELETE
- if (root == NULL)
- return root;
- // If the key to be deleted is smaller than the
- // root's key, then it lies in left subtree
- if ( key < root->key )
- root->left = deleteNode(root->left, key);
- // If the key to be deleted is greater than the
- // root's key, then it lies in right subtree
- else if( key > root->key )
- root->right = deleteNode(root->right, key);
- // if key is same as root's key, then This is
- // the node to be deleted
- else
- {
- // node with only one child or no child
- if( (root->left == NULL) || (root->right == NULL) )
- {
- struct Node *temp = root->left ? root->left :
- root->right;
- // No child case
- if (temp == NULL)
- {
- temp = root;
- root = NULL;
- }
- else // One child case
- *root = *temp; // Copy the contents of
- // the non-empty child
- free(temp);
- }
- else
- {
- // node with two children: Get the inorder
- // successor (smallest in the right subtree)
- struct Node* temp = minValueNode(root->right);
- // Copy the inorder successor's data to this node
- root->key = temp->key;
- // Delete the inorder successor
- root->right = deleteNode(root->right, temp->key);
- }
- }
- // If the tree had only one node then return
- if (root == NULL)
- return root;
- // STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
- root->height = 1 + max(height(root->left),
- height(root->right));
- // STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to
- // check whether this node became unbalanced)
- int balance = getBalance(root);
- // If this node becomes unbalanced, then there are 4 cases
- // Left Left Case
- if (balance > 1 && getBalance(root->left) >= 0)
- return rightRotate(root);
- // Left Right Case
- if (balance > 1 && getBalance(root->left) < 0)
- {
- root->left = leftRotate(root->left);
- return rightRotate(root);
- }
- // Right Right Case
- if (balance < -1 && getBalance(root->right) <= 0)
- return leftRotate(root);
- // Right Left Case
- if (balance < -1 && getBalance(root->right) > 0)
- {
- root->right = rightRotate(root->right);
- return leftRotate(root);
- }
- return root;
- }
|