Skip to content

Instantly share code, notes, and snippets.

@squiidz
Last active January 31, 2023 15:22
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save squiidz/996129e16d870a8244fcaa7010ee8b5c to your computer and use it in GitHub Desktop.
Save squiidz/996129e16d870a8244fcaa7010ee8b5c to your computer and use it in GitHub Desktop.
Btree implementation in C
#include "stdio.h"
#include "stdlib.h"
#define M 3
typedef struct _node {
int n; /* n < M No. of keys in node will always less than order of B tree */
int keys[M - 1]; /*array of keys*/
struct _node *p[M]; /* (n+1 pointers will be in use) */
} node;
node *root = NULL;
typedef enum KeyStatus {
Duplicate,
SearchFailure,
Success,
InsertIt,
LessKeys,
} KeyStatus;
void insert(int key);
void display(node *root, int);
void DelNode(int x);
void search(int x);
KeyStatus ins(node *r, int x, int* y, node** u);
int searchPos(int x, int *key_arr, int n);
KeyStatus del(node *r, int x);
void eatline(void);
void inorder(node *ptr);
int totalKeys(node *ptr);
void printTotal(node *ptr);
int getMin(node *ptr);
int getMax(node *ptr);
void getMinMax(node *ptr);
int max(int first, int second, int third);
int maxLevel(node *ptr);
void printMaxLevel(node *ptr);
int main() {
int key;
int choice;
printf("Creation of B tree for M=%d\n", M);
while (1) {
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Search\n");
printf("4.Display\n");
printf("5.Quit\n");
printf("6.Enumerate\n");
printf("7.Total Keys\n");
printf("8.Min and Max Keys\n");
printf("9.Max Level\n");
printf("Enter your choice : ");
scanf("%d", &choice); eatline();
switch (choice) {
case 1:
printf("Enter the key : ");
scanf("%d", &key); eatline();
insert(key);
break;
case 2:
printf("Enter the key : ");
scanf("%d", &key); eatline();
DelNode(key);
break;
case 3:
printf("Enter the key : ");
scanf("%d", &key); eatline();
search(key);
break;
case 4:
printf("Btree is :\n");
display(root, 0);
break;
case 5:
exit(1);
case 6:
printf("Btree in sorted order is:\n");
inorder(root); putchar('\n');
break;
case 7:
printf("The total number of keys in this tree is:\n");
printTotal(root);
break;
case 8:
getMinMax(root);
break;
case 9:
printf("The maximum level in this tree is:\n");
printMaxLevel(root);
break;
default:
printf("Wrong choice\n");
break;
}/*End of switch*/
}/*End of while*/
return 0;
}/*End of main()*/
void insert(int key) {
node *newnode;
int upKey;
KeyStatus value;
value = ins(root, key, &upKey, &newnode);
if (value == Duplicate)
printf("Key already available\n");
if (value == InsertIt) {
node *uproot = root;
root = (node*)malloc(sizeof(node));
root->n = 1;
root->keys[0] = upKey;
root->p[0] = uproot;
root->p[1] = newnode;
}/*End of if */
}/*End of insert()*/
KeyStatus ins(node *ptr, int key, int *upKey, node **newnode) {
node *newPtr, *lastPtr;
int pos, i, n, splitPos;
int newKey, lastKey;
KeyStatus value;
if (ptr == NULL) {
*newnode = NULL;
*upKey = key;
return InsertIt;
}
n = ptr->n;
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos])
return Duplicate;
value = ins(ptr->p[pos], key, &newKey, &newPtr);
if (value != InsertIt)
return value;
/*If keys in node is less than M-1 where M is order of B tree*/
if (n < M - 1) {
pos = searchPos(newKey, ptr->keys, n);
/*Shifting the key and pointer right for inserting the new key*/
for (i = n; i>pos; i--) {
ptr->keys[i] = ptr->keys[i - 1];
ptr->p[i + 1] = ptr->p[i];
}
/*Key is inserted at exact location*/
ptr->keys[pos] = newKey;
ptr->p[pos + 1] = newPtr;
++ptr->n; /*incrementing the number of keys in node*/
return Success;
}/*End of if */
/*If keys in nodes are maximum and position of node to be inserted is last*/
if (pos == M - 1) {
lastKey = newKey;
lastPtr = newPtr;
}
else { /*If keys in node are maximum and position of node to be inserted is not last*/
lastKey = ptr->keys[M - 2];
lastPtr = ptr->p[M - 1];
for (i = M - 2; i>pos; i--) {
ptr->keys[i] = ptr->keys[i - 1];
ptr->p[i + 1] = ptr->p[i];
}
ptr->keys[pos] = newKey;
ptr->p[pos + 1] = newPtr;
}
splitPos = (M - 1) / 2;
(*upKey) = ptr->keys[splitPos];
(*newnode) = (node*)malloc(sizeof(node));/*Right node after split*/
ptr->n = splitPos; /*No. of keys for left splitted node*/
(*newnode)->n = M - 1 - splitPos;/*No. of keys for right splitted node*/
for (i = 0; i < (*newnode)->n; i++) {
(*newnode)->p[i] = ptr->p[i + splitPos + 1];
if (i < (*newnode)->n - 1)
(*newnode)->keys[i] = ptr->keys[i + splitPos + 1];
else
(*newnode)->keys[i] = lastKey;
}
(*newnode)->p[(*newnode)->n] = lastPtr;
return InsertIt;
}/*End of ins()*/
void display(node *ptr, int blanks) {
if (ptr) {
int i;
for (i = 1; i <= blanks; i++)
printf(" ");
for (i = 0; i < ptr->n; i++)
printf("%d ", ptr->keys[i]);
printf("\n");
for (i = 0; i <= ptr->n; i++)
display(ptr->p[i], blanks + 10);
}/*End of if*/
}/*End of display()*/
void search(int key) {
int pos, i, n;
node *ptr = root;
printf("Search path:\n");
while (ptr) {
n = ptr->n;
for (i = 0; i < ptr->n; i++)
printf(" %d", ptr->keys[i]);
printf("\n");
pos = searchPos(key, ptr->keys, n);
if (pos < n && key == ptr->keys[pos]) {
printf("Key %d found in position %d of last dispalyed node\n", key, i);
return;
}
ptr = ptr->p[pos];
}
printf("Key %d is not available\n", key);
}/*End of search()*/
int searchPos(int key, int *key_arr, int n) {
int pos = 0;
while (pos < n && key > key_arr[pos])
pos++;
return pos;
}/*End of searchPos()*/
void DelNode(int key) {
node *uproot;
KeyStatus value;
value = del(root, key);
switch (value) {
case SearchFailure:
printf("Key %d is not available\n", key);
break;
case LessKeys:
uproot = root;
root = root->p[0];
free(uproot);
break;
default:
return;
}/*End of switch*/
}/*End of delnode()*/
KeyStatus del(node *ptr, int key) {
int pos, i, pivot, n, min;
int *key_arr;
KeyStatus value;
node **p, *lptr, *rptr;
if (ptr == NULL)
return SearchFailure;
/*Assigns values of node*/
n = ptr->n;
key_arr = ptr->keys;
p = ptr->p;
min = (M - 1) / 2;/*Minimum number of keys*/
//Search for key to delete
pos = searchPos(key, key_arr, n);
// p is a leaf
if (p[0] == NULL) {
if (pos == n || key < key_arr[pos])
return SearchFailure;
/*Shift keys and pointers left*/
for (i = pos + 1; i < n; i++)
{
key_arr[i - 1] = key_arr[i];
p[i] = p[i + 1];
}
return --ptr->n >= (ptr == root ? 1 : min) ? Success : LessKeys;
}/*End of if */
//if found key but p is not a leaf
if (pos < n && key == key_arr[pos]) {
node *qp = p[pos], *qp1;
int nkey;
while (1) {
nkey = qp->n;
qp1 = qp->p[nkey];
if (qp1 == NULL)
break;
qp = qp1;
}/*End of while*/
key_arr[pos] = qp->keys[nkey - 1];
qp->keys[nkey - 1] = key;
}/*End of if */
value = del(p[pos], key);
if (value != LessKeys)
return value;
if (pos > 0 && p[pos - 1]->n > min) {
pivot = pos - 1; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pos];
/*Assigns values for right node*/
rptr->p[rptr->n + 1] = rptr->p[rptr->n];
for (i = rptr->n; i>0; i--) {
rptr->keys[i] = rptr->keys[i - 1];
rptr->p[i] = rptr->p[i - 1];
}
rptr->n++;
rptr->keys[0] = key_arr[pivot];
rptr->p[0] = lptr->p[lptr->n];
key_arr[pivot] = lptr->keys[--lptr->n];
return Success;
}/*End of if */
//if (posn > min)
if (pos < n && p[pos + 1]->n > min) {
pivot = pos; /*pivot for left and right node*/
lptr = p[pivot];
rptr = p[pivot + 1];
/*Assigns values for left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
key_arr[pivot] = rptr->keys[0];
lptr->n++;
rptr->n--;
for (i = 0; i < rptr->n; i++) {
rptr->keys[i] = rptr->keys[i + 1];
rptr->p[i] = rptr->p[i + 1];
}/*End of for*/
rptr->p[rptr->n] = rptr->p[rptr->n + 1];
return Success;
}/*End of if */
if (pos == n)
pivot = pos - 1;
else
pivot = pos;
lptr = p[pivot];
rptr = p[pivot + 1];
/*merge right node with left node*/
lptr->keys[lptr->n] = key_arr[pivot];
lptr->p[lptr->n + 1] = rptr->p[0];
for (i = 0; i < rptr->n; i++) {
lptr->keys[lptr->n + 1 + i] = rptr->keys[i];
lptr->p[lptr->n + 2 + i] = rptr->p[i + 1];
}
lptr->n = lptr->n + rptr->n + 1;
free(rptr); /*Remove right node*/
for (i = pos + 1; i < n; i++) {
key_arr[i - 1] = key_arr[i];
p[i] = p[i + 1];
}
return --ptr->n >= (ptr == root ? 1 : min) ? Success : LessKeys;
}/*End of del()*/
void eatline(void) {
char c;
while ((c = getchar()) != '\n');
}
/* Function to display each key in the tree in sorted order (in-order traversal)
@param struct node *ptr, the pointer to the node you are currently working with
*/
void inorder(node *ptr) {
if (ptr) {
if (ptr->n >= 1) {
inorder(ptr->p[0]);
printf("%d ", ptr->keys[0]);
inorder(ptr->p[1]);
if (ptr->n == 2) {
printf("%d ", ptr->keys[1]);
inorder(ptr->p[2]);
}
}
}
}
/* Function that returns the total number of keys in the tree.
@param struct node *ptr, the pointer to the node you are currently working with
*/
int totalKeys(node *ptr) {
if (ptr) {
int count = 1;
if (ptr->n >= 1) {
count += totalKeys(ptr->p[0]);
count += totalKeys(ptr->p[1]);
if (ptr->n == 2) count += totalKeys(ptr->p[2]) + 1;
}
return count;
}
return 0;
}
/* Function that prints the total number of keys in the tree.
@param struct node *ptr, the pointer to the node you are currently working with
*/
void printTotal(node *ptr) {
printf("%d\n", totalKeys(ptr));
}
/* Function that returns the smallest key found in the tree.
@param struct node *ptr, the pointer to the node you are currently working with
*/
int getMin(node *ptr) {
if (ptr) {
int min;
if (ptr->p[0] != NULL) min = getMin(ptr->p[0]);
else min = ptr->keys[0];
return min;
}
return 0;
}
/* Function that returns the largest key found in the tree.
@param struct node *ptr, the pointer to the node you are currently working with
*/
int getMax(node *ptr) {
if (ptr) {
int max;
if (ptr->n == 1) {
if (ptr->p[1] != NULL) max = getMax(ptr->p[1]);
else max = ptr->keys[0];
}
if (ptr->n == 2) {
if (ptr->p[2] != NULL) max = getMax(ptr->p[2]);
else max = ptr->keys[1];
}
return max;
}
return 0;
}
/* Function that prints the smallest and largest keys found in the tree.
@param struct node *ptr, the pointer to the node you are currently working with
*/
void getMinMax(node *ptr) {
printf("%d %d\n", getMin(ptr), getMax(ptr));
}
/* Function that determines the largest number.
@param int, integer to compare.
@param int, integer to compare.
@param int, integer to compare.
*/
int max(int first, int second, int third) {
int max = first;
if (second > max) max = second;
if (third > max) max = third;
return max;
}
/*Function that finds the maximum level in the node and returns it as an integer.
@param struct node *ptr, the node to find the maximum level for.
*/
int maxLevel(node *ptr) {
if (ptr) {
int l = 0, mr = 0, r = 0, max_depth;
if (ptr->p[0] != NULL) l = maxLevel(ptr->p[0]);
if (ptr->p[1] != NULL) mr = maxLevel(ptr->p[1]);
if (ptr->n == 2) {
if (ptr->p[2] != NULL) r = maxLevel(ptr->p[2]);
}
max_depth = max(l, mr, r) + 1;
return max_depth;
}
return 0;
}
/*Function that prints the maximum level in the tree.
@param struct node *ptr, the tree to find the maximum level for.
*/
void printMaxLevel(node *ptr) {
int max = maxLevel(ptr) - 1;
if (max == -1) printf("tree is empty\n");
else printf("%d\n", max);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment