Skip to content

Instantly share code, notes, and snippets.

@ziap
Last active August 7, 2024 06:03
Show Gist options
  • Save ziap/56baf02797c6037f763b3303947462dc to your computer and use it in GitHub Desktop.
Save ziap/56baf02797c6037f763b3303947462dc to your computer and use it in GitHub Desktop.
AVL tree implementation in C
#include <stdlib.h>
#include <stdint.h>
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
typedef enum {
SIDE_LEFT = 0,
SIDE_RIGHT,
SIDE_COUNT,
} AVL_Side;
typedef struct AVL_Node AVL_Node;
typedef int KeyType;
struct AVL_Node {
KeyType key;
int8_t height;
AVL_Node *children[SIDE_COUNT];
};
static AVL_Node NIL_NODE = {
.height = 0,
.children = {NULL, NULL}
};
static AVL_Node *NIL = &NIL_NODE;
static void AVL_update_height(AVL_Node *node) {
node->height = 1 + MAX(node->children[SIDE_LEFT]->height,
node->children[SIDE_RIGHT]->height);
}
static int8_t AVL_balance_factor(AVL_Node *node, AVL_Side side) {
return node->children[side]->height - node->children[!side]->height;
}
static void AVL_rotate(AVL_Node **node, AVL_Side side) {
AVL_Node *temp = (*node)->children[!side];
(*node)->children[!side] = temp->children[side];
AVL_update_height(*node);
temp->children[side] = *node;
AVL_update_height(temp);
*node = temp;
}
static void AVL_balance(AVL_Node **node, AVL_Side side) {
AVL_update_height(*node);
if (AVL_balance_factor(*node, side) > 1) {
AVL_Node **child = &(*node)->children[side];
if (AVL_balance_factor(*child, side) < 0) {
AVL_rotate(child, side);
}
AVL_rotate(node, !side);
}
}
void AVL_insert(AVL_Node **node, KeyType data) {
if ((*node) == NIL) {
AVL_Node *new_node = malloc(sizeof(AVL_Node));
new_node->key = data;
new_node->children[SIDE_LEFT] = NIL;
new_node->children[SIDE_RIGHT] = NIL;
new_node->height = 1;
*node = new_node;
return;
}
if ((*node)->key == data) return;
AVL_Side side = data > (*node)->key;
AVL_insert(&(*node)->children[side], data);
AVL_balance(node, side);
}
static KeyType AVL_remove_succ(AVL_Node **node) {
if ((*node)->children[SIDE_LEFT] != NIL) {
KeyType val = AVL_remove_succ(&(*node)->children[SIDE_LEFT]);
AVL_balance(node, SIDE_RIGHT);
return val;
}
KeyType val = (*node)->key;
AVL_Node *child = (*node)->children[SIDE_RIGHT];
free(*node);
*node = child;
return val;
}
void AVL_remove(AVL_Node **node, KeyType data) {
if ((*node) == NIL) {
return;
}
if ((*node)->key == data) {
if ((*node)->children[SIDE_LEFT] != NIL && (*node)->children[SIDE_RIGHT] != NIL) {
(*node)->key = AVL_remove_succ(&(*node)->children[SIDE_RIGHT]);
AVL_balance(node, SIDE_LEFT);
return;
}
AVL_Node *child = (*node)->children[SIDE_LEFT];
if (child == NIL) child = (*node)->children[SIDE_RIGHT];
free(*node);
*node = child;
return;
}
AVL_Side side = data > (*node)->key;
AVL_remove(&(*node)->children[side], data);
AVL_balance(node, !side);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment