From ab31448a9be6080340e92b5d111a6c700f55e0c8 Mon Sep 17 00:00:00 2001 From: kirebr Date: Tue, 9 Oct 2018 14:59:35 -0300 Subject: [PATCH 1/2] b-tree C --- trees/B-Tree/C/bTree.c | 198 +++++++++++++++++++++++++++++++++++++++++ trees/B-Tree/C/bTree.h | 17 ++++ 2 files changed, 215 insertions(+) create mode 100644 trees/B-Tree/C/bTree.c create mode 100644 trees/B-Tree/C/bTree.h diff --git a/trees/B-Tree/C/bTree.c b/trees/B-Tree/C/bTree.c new file mode 100644 index 0000000000..1c5b843501 --- /dev/null +++ b/trees/B-Tree/C/bTree.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include + +#include "bTree.h" + +#define MAX_KEYS (1024) + +struct btNode { + int isLeaf; /* is this a leaf node? */ + int numKeys; /* how many keys does this node contain? */ + int keys[MAX_KEYS]; + struct btNode *kids[MAX_KEYS+1]; /* kids[i] holds nodes < keys[i] */ +}; + +bTree +btCreate(void) +{ + bTree b; + + b = malloc(sizeof(*b)); + assert(b); + + b->isLeaf = 1; + b->numKeys = 0; + + return b; +} + +void +btDestroy(bTree b) +{ + int i; + + if(!b->isLeaf) { + for(i = 0; i < b->numKeys + 1; i++) { + btDestroy(b->kids[i]); + } + } + + free(b); +} + +/* return smallest index i in sorted array such that key <= a[i] */ +/* (or n if there is no such index) */ +static int +searchKey(int n, const int *a, int key) +{ + int lo; + int hi; + int mid; + + /* invariant: a[lo] < key <= a[hi] */ + lo = -1; + hi = n; + + while(lo + 1 < hi) { + mid = (lo+hi)/2; + if(a[mid] == key) { + return mid; + } else if(a[mid] < key) { + lo = mid; + } else { + hi = mid; + } + } + + return hi; +} + +int +btSearch(bTree b, int key) +{ + int pos; + + /* have to check for empty tree */ + if(b->numKeys == 0) { + return 0; + } + + /* look for smallest position that key fits below */ + pos = searchKey(b->numKeys, b->keys, key); + + if(pos < b->numKeys && b->keys[pos] == key) { + return 1; + } else { + return(!b->isLeaf && btSearch(b->kids[pos], key)); + } +} + +/* insert a new key into a tree */ +/* returns new right sibling if the node splits */ +/* and puts the median in *median */ +/* else returns 0 */ +static bTree +btInsertInternal(bTree b, int key, int *median) +{ + int pos; + int mid; + bTree b2; + + pos = searchKey(b->numKeys, b->keys, key); + + if(pos < b->numKeys && b->keys[pos] == key) { + /* nothing to do */ + return 0; + } + + if(b->isLeaf) { + + /* everybody above pos moves up one space */ + memmove(&b->keys[pos+1], &b->keys[pos], sizeof(*(b->keys)) * (b->numKeys - pos)); + b->keys[pos] = key; + b->numKeys++; + + } else { + + /* insert in child */ + b2 = btInsertInternal(b->kids[pos], key, &mid); + + /* maybe insert a new key in b */ + if(b2) { + + /* every key above pos moves up one space */ + memmove(&b->keys[pos+1], &b->keys[pos], sizeof(*(b->keys)) * (b->numKeys - pos)); + /* new kid goes in pos + 1*/ + memmove(&b->kids[pos+2], &b->kids[pos+1], sizeof(*(b->keys)) * (b->numKeys - pos)); + + b->keys[pos] = mid; + b->kids[pos+1] = b2; + b->numKeys++; + } + } + + /* we waste a tiny bit of space by splitting now + * instead of on next insert */ + if(b->numKeys >= MAX_KEYS) { + mid = b->numKeys/2; + + *median = b->keys[mid]; + + /* make a new node for keys > median */ + /* picture is: + * + * 3 5 7 + * A B C D + * + * becomes + * (5) + * 3 7 + * A B C D + */ + b2 = malloc(sizeof(*b2)); + + b2->numKeys = b->numKeys - mid - 1; + b2->isLeaf = b->isLeaf; + + memmove(b2->keys, &b->keys[mid+1], sizeof(*(b->keys)) * b2->numKeys); + if(!b->isLeaf) { + memmove(b2->kids, &b->kids[mid+1], sizeof(*(b->kids)) * (b2->numKeys + 1)); + } + + b->numKeys = mid; + + return b2; + } else { + return 0; + } +} + +void +btInsert(bTree b, int key) +{ + bTree b1; /* new left child */ + bTree b2; /* new right child */ + int median; + + b2 = btInsertInternal(b, key, &median); + + if(b2) { + /* basic issue here is that we are at the root */ + /* so if we split, we have to make a new root */ + + b1 = malloc(sizeof(*b1)); + assert(b1); + + /* copy root to b1 */ + memmove(b1, b, sizeof(*b)); + + /* make root point to b1 and b2 */ + b->numKeys = 1; + b->isLeaf = 0; + b->keys[0] = median; + b->kids[0] = b1; + b->kids[1] = b2; + } +} diff --git a/trees/B-Tree/C/bTree.h b/trees/B-Tree/C/bTree.h new file mode 100644 index 0000000000..1ab71acf54 --- /dev/null +++ b/trees/B-Tree/C/bTree.h @@ -0,0 +1,17 @@ +/* implementation of a B-tree */ +typedef struct btNode *bTree; + +/* create a new empty tree */ +bTree btCreate(void); + +/* free a tree */ +void btDestroy(bTree t); + +/* return nonzero if key is present in tree */ +int btSearch(bTree t, int key); + +/* insert a new element into a tree */ +void btInsert(bTree t, int key); + +/* print all keys of the tree in order */ +void btPrintKeys(bTree t); From 7e2e0a714a64f65f818d6fa617ca1dd7677f019a Mon Sep 17 00:00:00 2001 From: kirebr Date: Thu, 18 Oct 2018 13:51:42 -0300 Subject: [PATCH 2/2] modified tree --- {trees => data_structures/Tree}/B-Tree/C/bTree.c | 0 {trees => data_structures/Tree}/B-Tree/C/bTree.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {trees => data_structures/Tree}/B-Tree/C/bTree.c (100%) rename {trees => data_structures/Tree}/B-Tree/C/bTree.h (100%) diff --git a/trees/B-Tree/C/bTree.c b/data_structures/Tree/B-Tree/C/bTree.c similarity index 100% rename from trees/B-Tree/C/bTree.c rename to data_structures/Tree/B-Tree/C/bTree.c diff --git a/trees/B-Tree/C/bTree.h b/data_structures/Tree/B-Tree/C/bTree.h similarity index 100% rename from trees/B-Tree/C/bTree.h rename to data_structures/Tree/B-Tree/C/bTree.h