Skip to content

Commit

Permalink
Fix iiitv#519: Add AVL Tree [C] (iiitv#521)
Browse files Browse the repository at this point in the history
* Added AVL Tree [C]

* Fixed whitespace requirements
  • Loading branch information
Muwbi authored and singhpratyush committed Oct 26, 2017
1 parent 0b52cc7 commit d14c9f6
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Community (college) maintained list of Algorithms and Data Structures implementa

| Data Structure | C | CPP | Java | Python | Golang | JavaScript | C# |
|:--------------|:----------------:|:----------------:|:----------------:|:-----------------:|:-----------------:|:-----------------:|:-----------------:|
| [AVL Tree](http://www.geeksforgeeks.org/avl-tree-set-1-insertion)| | |[:white_check_mark:](avl_tree/AvlTree.java) | | | | |
| [AVL Tree](http://www.geeksforgeeks.org/avl-tree-set-1-insertion)|[:white_check_mark:](avl_tree/avl_tree.c)| |[:white_check_mark:](avl_tree/AvlTree.java) | | | | |
| [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree) | | | [:white_check_mark:](binary_search_tree/BinarySearchTree.java) | | [:white_check_mark:](binary_search_tree/binary_search_tree.go) | | |
| [Linked List](https://en.wikipedia.org/wiki/Linked_list) | [:white_check_mark:](linked_list/linkedList.c.c) | | [:white_check_mark:](linked_list/LinkedList.java) | [:white_check_mark:](linked_list/linked_list.py) | [:white_check_mark:](linked_list/linked_list.go) | [:white_check_mark:](linked_list/linkedList.js) | [:white_check_mark:](linked_list/LinkedList.cs) |
| [Stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)) | [:white_check_mark:](stack/stack.c) | | [:white_check_mark:](stack/Stack.java) | [:white_check_mark:](stack/stack.py) | [:white_check_mark:](stack/stack.go) | [:white_check_mark:](stack/stack.js) | [:white_check_mark:](stack/Stack.cs) |
Expand Down
203 changes: 203 additions & 0 deletions avl_tree/avl_tree.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
// Implements an AVL tree in C

#include <stdlib.h>
#include <stdio.h>

#define max(a,b) (((a)>(b))?(a):(b))

typedef struct AVLNode {
struct AVLNode* left; // left child node
struct AVLNode* right; // right child node
struct AVLNode* parent; // parent node
int value; // integer type data
int height; // current height in the tree
} AVLNode;

typedef struct AVLTree {
struct AVLNode* root; // the tree's root node
int size; // the tree's size
} AVLTree;


// Adjusts the height of the given node respective to its current position
void adjust_height(AVLNode* avln) {
if (avln->left == NULL && avln->right == NULL) {
avln->height = 1;
} else if (avln->left == NULL) {
avln->height = 1 + avln->right->height;
} else if (avln->right == NULL) {
avln->height = 1 + avln->left->height;
} else {
avln->height = 1 + max(avln->left->height, avln->right->height);
}
}

// Performs a left rotation on the given node in the given tree
void rotate_left(AVLTree* avlt, AVLNode* avln) {
AVLNode* y = avln->right;
avln->right = y->left;

if (y->left != NULL) {
y->left->parent = avln;
}

y->parent = avln->parent;

if (avln->parent == NULL) {
avlt->root = y;
} else if (avln->value == avln->parent->left->value) {
avln->parent->left = y;
} else {
avln->parent->right = y;
}

y->left = avln;
avln->parent = y;

adjust_height(avln);
adjust_height(y);
}

// Performs a right rotation on the given node in the given tree
void rotate_right(AVLTree* avlt, AVLNode* avln) {
AVLNode* x = avln->left;
avln->left = x->right;

if (x->right != NULL) {
x->right->parent = avln;
}

x->parent = avln->parent;

if (avln->parent == NULL) {
avlt->root = x;
} else if (avln->value == avln->parent->right->value) {
avln->parent->right = x;
} else {
avln->parent->left = x;
}

x->right = avln;
avln->parent = x;

adjust_height(avln);
adjust_height(x);
}

// Helper method to get the height of the given node
// Used to easily implement the required NULL-checks
int get_height(AVLNode* avln) {
if (avln == NULL) {
return 0;
} else {
return avln->height;
}
}

// Helper method to get the height of the node to the left
// Used to easily implement the required NULL-checks
int get_left_height(AVLNode* avln) {
if (avln == NULL || avln->left == NULL) {
return 0;
} else {
return avln->left->height;
}
}

// Helper method to get the height of the node to the right
// Used to easily implement the required NULL-checks
int get_right_height(AVLNode* avln) {
if (avln == NULL || avln->right == NULL) {
return 0;
} else {
return avln->right->height;
}
}

// Balances the sub-tree below the given node
void balance(AVLTree* avlt, AVLNode* avln) {
// check if the tree is left-heavy
if (get_height(avln->left) > get_height(avln->right) + 1) {
if (get_left_height(avln->left) < get_right_height(avln->left)) {
rotate_left(avlt, avln->left);
}
rotate_right(avlt, avln);

// check if the tree is right-heavy
} else if (get_height(avln->right) > get_height(avln->left) + 1) {
if (get_right_height(avln->right) < get_left_height(avln->right)) {
rotate_right(avlt, avln->right);
}
rotate_left(avlt, avln);
}
}

// Recursive method to insert a value into the tree, NOT to be used by the outside
void insert_value_recursive(AVLTree* avlt, AVLNode** avln, AVLNode* parent, int value) {
// If the given node is NULL (i.e. the tree is empty or we have reached a leaf node)
if (*avln == NULL) {
*avln = malloc(sizeof(AVLNode));
(*avln)->left = NULL;
(*avln)->right = NULL;
(*avln)->parent = parent;
(*avln)->value = value;
(*avln)->height = 1;

avlt->size++;

// If the the given value is lower than the currently viewed node, view the left child
} else if (value < (*avln)->value) {
insert_value_recursive(avlt, &(*avln)->left, *avln, value);

// If the the given value is greater than the currently viewed node, view the right child
} else if (value > (*avln)->value) {
insert_value_recursive(avlt, &(*avln)->right, *avln, value);

// If the the given value is equal to the currently viewed node, return because we don't allow double entries
} else {
return;
}

// Determine the height of the newly created node
(*avln)->height = 1 + max(get_height((*avln)->left), get_height((*avln)->right));

// Re-balance the node to check for possibly needed rotations
balance(avlt, *avln);
}

// Inserts the given value into the tree
void insert_value(AVLTree* avlt, int value) {
// Use the recursive function to allow the function to correctly position the newly created node
insert_value_recursive(avlt, &avlt->root, NULL, value);
}

void traverse_in_order(AVLNode* avln) {
if (avln != NULL) {
// traverse the left sub-tree first
traverse_in_order(avln->left);

// print the current node's value
printf("%d ", avln->value);

// traverse the right sub-tree later
traverse_in_order(avln->right);
}
}

int main() {
// create a new AVLTree
AVLTree avlt;
avlt.root = NULL;
avlt.size = 0;

insert_value(&avlt, 2);
insert_value(&avlt, 5);
insert_value(&avlt, 7);
insert_value(&avlt, 3);
insert_value(&avlt, 10);
insert_value(&avlt, 1);
insert_value(&avlt, 20);

traverse_in_order((&avlt)->root);
printf("\n");
}

0 comments on commit d14c9f6

Please sign in to comment.