Mercurial > data_structures
changeset 18:ef2c6a831fb9
Btree taking shape. Insert seems to be working
author | Eris Caffee <discordia@eldalin.com> |
---|---|
date | Wed, 17 Oct 2012 02:17:47 -0500 |
parents | 36561a63330a |
children | 0bf94d0ed0b0 |
files | CMakeLists.txt src/btree_mem.c src/btree_mem.h src/btree_mem_test.c |
diffstat | 4 files changed, 173 insertions(+), 29 deletions(-) [+] |
line diff
1.1 --- a/CMakeLists.txt Tue Oct 16 19:57:23 2012 -0500 1.2 +++ b/CMakeLists.txt Wed Oct 17 02:17:47 2012 -0500 1.3 @@ -27,7 +27,7 @@ 1.4 1.5 1.6 if (CMAKE_COMPILER_IS_GNUCXX) 1.7 - add_definitions(-pedantic -Wall -std=gnu99) 1.8 + add_definitions(-pedantic -Wall -std=gnu99 -O0) 1.9 endif () 1.10 1.11
2.1 --- a/src/btree_mem.c Tue Oct 16 19:57:23 2012 -0500 2.2 +++ b/src/btree_mem.c Wed Oct 17 02:17:47 2012 -0500 2.3 @@ -1,3 +1,8 @@ 2.4 +/* 2.5 + This is a fairly straightforward implementation of a B-Tree in memory modeled after 2.6 + Cormen, et al., Introduction to Algorithms, Chapter 18 2.7 + */ 2.8 + 2.9 #include <stdio.h> 2.10 2.11 #include <stdlib.h> 2.12 @@ -5,7 +10,6 @@ 2.13 2.14 #include "btree_mem.h" 2.15 2.16 -// In btree_mem_node, child[0].keys <= key[0] < child[1].keys <= key[1] < child[2].keys ... 2.17 struct btree_mem_node 2.18 { 2.19 int nkeys; 2.20 @@ -15,13 +19,17 @@ 2.21 bool leaf; 2.22 }; 2.23 2.24 -struct btree_mem_node * btree_mem_node_new (struct btree_mem * bt); 2.25 -void btree_mem_node_delete (struct btree_mem_node * node); 2.26 +struct btree_mem_node * btree_mem_node_new (struct btree_mem * bt); 2.27 +void btree_mem_node_delete (struct btree_mem_node * node); 2.28 2.29 -struct btree_mem_node * btree_mem_node_find (struct btree_mem * bt, struct btree_mem_node * node, void * key, int * i); 2.30 +struct btree_mem_node * btree_mem_node_find (struct btree_mem * bt, struct btree_mem_node * node, void * key, int * i); 2.31 2.32 -void * btree_mem_node_insert (struct btree_mem * bt, struct btree_mem_node * node, void * key, void * data); 2.33 -struct btree_mem_node * btree_mem_split_child (struct btree_mem * bt, struct btree_mem_node * x, int i, struct btree_mem_node * y); 2.34 +void * btree_mem_node_insert (struct btree_mem * bt, struct btree_mem_node * node, void * key, void * data); 2.35 +void * btree_mem_node_insert_nonfull (struct btree_mem * bt, struct btree_mem_node * node, void * key, void * data); 2.36 + 2.37 +struct btree_mem_node * btree_mem_split_child (struct btree_mem * bt, struct btree_mem_node * x, int i); 2.38 + 2.39 +void btree_mem_node_walk_inorder (struct btree_mem_node * node, void (*f)(int, void *, void *), int depth); 2.40 2.41 //////////////////////////////////////////////////////////////////////////////// 2.42 struct btree_mem * 2.43 @@ -41,6 +49,7 @@ 2.44 return NULL; 2.45 } 2.46 2.47 + bt->root->leaf = true; 2.48 return bt; 2.49 } 2.50 2.51 @@ -88,6 +97,14 @@ 2.52 return NULL; 2.53 } 2.54 2.55 + for (int i = 0; i < maxchild - 1; i++) 2.56 + { 2.57 + node->key[i] = NULL; 2.58 + node->data[i] = NULL; 2.59 + node->child[i] = NULL; 2.60 + } 2.61 + node->child[maxchild-1] = NULL; 2.62 + 2.63 node->nkeys = 0; 2.64 node->leaf = false; 2.65 2.66 @@ -136,39 +153,82 @@ 2.67 void * 2.68 btree_mem_insert(struct btree_mem * bt, void * key, void * data) 2.69 { 2.70 - return btree_mem_node_insert(bt, bt->root, key, data); 2.71 + struct btree_mem_node * s = bt->root; 2.72 + 2.73 + printf("inserting >%d< >%s<\n", *((int *) key), (char *) data); 2.74 + // If the root node is full, split it here. 2.75 + if ((2 * bt->mindeg - 1) == s->nkeys) 2.76 + { 2.77 + printf("Root node is full: splitting\n"); 2.78 + s = btree_mem_node_new(bt); 2.79 + if (NULL == s) 2.80 + return NULL; 2.81 + s->child[0] = bt->root; 2.82 + bt->root = s; 2.83 + btree_mem_split_child(bt, s, 0); 2.84 + } 2.85 + return btree_mem_node_insert_nonfull(bt, s, key, data); 2.86 } 2.87 2.88 //////////////////////////////////////////////////////////////////////////////// 2.89 void * 2.90 -btree_mem_node_insert(struct btree_mem * bt, struct btree_mem_node * node, void * key, void * data) 2.91 +btree_mem_node_insert_nonfull(struct btree_mem * bt, struct btree_mem_node * node, void * key, void * data) 2.92 { 2.93 - struct btree_node * r = bt->root; 2.94 - if ((2 * bt->mindeg - 1) == node->nkeys) 2.95 + int i = node->nkeys - 1; 2.96 + if (node->leaf) 2.97 { 2.98 - struct btree_node * s = btree_mem_node_new(bt); 2.99 - if (NULL == s) 2.100 - return NULL; 2.101 - bt->root = s; 2.102 - s->child[0] = r; 2.103 - btree_mem_split_child(bt, s, 1, r); 2.104 - r = s; 2.105 + printf("node is leaf: inserting\n"); 2.106 + while ( (i >= 0) && (bt->cmp(key, node->key[i]) < 0) ) 2.107 + { 2.108 + node->key[i+1] = node->key[i]; 2.109 + i--; 2.110 + } 2.111 + node->key[i+1] = key; 2.112 + node->data[i+1] = data; 2.113 + node->nkeys++; 2.114 + return key; 2.115 } 2.116 - return btree_mem_node_insert(bt, s, key, data); 2.117 + else 2.118 + { 2.119 + printf("node is not leaf: recursing\n"); 2.120 + while ( (i >= 0) && (bt->cmp(key, node->key[i]) < 0) ) 2.121 + i--; 2.122 + i++; 2.123 + printf("i %d\n", i); 2.124 + 2.125 + /* // Does the child exist? If not we need to allocate it */ 2.126 + /* if (NULL == node->child[i]) */ 2.127 + /* { */ 2.128 + /* node->child[i] = btree_mem_node_new(bt); */ 2.129 + /* if (NULL == node->child[i]) */ 2.130 + /* return NULL; */ 2.131 + /* } */ 2.132 + 2.133 + if (node->child[i]->nkeys == (2 * bt->mindeg - 1)) 2.134 + { 2.135 + printf("splitting before recursion\n"); 2.136 + if (NULL == btree_mem_split_child(bt, node, i)) 2.137 + return NULL; 2.138 + if (bt->cmp(key, node->key[i]) > 0) 2.139 + i++; 2.140 + } 2.141 + return btree_mem_node_insert_nonfull(bt, node->child[i], key, data); 2.142 + } 2.143 } 2.144 2.145 //////////////////////////////////////////////////////////////////////////////// 2.146 // x - a non-full node 2.147 -// y - a full node that is a child of x 2.148 -// i - The index of y in x's child list. That is x->child[i] == y. 2.149 +// i - The index of a full node y in x's child list. 2.150 // 2.151 // Split y in half, adding the newly created node z as a new child of x. 2.152 // z will be placed after y in the child list. 2.153 2.154 struct btree_mem_node * 2.155 -btree_mem_split_child(struct btree_mem * bt, struct btree_mem_node * x, int i, struct btree_mem_node * y) 2.156 +btree_mem_split_child(struct btree_mem * bt, struct btree_mem_node * x, int i) 2.157 { 2.158 2.159 + struct btree_mem_node * y = x->child[i]; 2.160 + 2.161 // Allocate new node. 2.162 struct btree_mem_node * z = btree_mem_node_new(bt); 2.163 if (NULL == z) 2.164 @@ -184,20 +244,20 @@ 2.165 } 2.166 if (! y->leaf) 2.167 { 2.168 - for (int j = 0; j < bt->mindeg) 2.169 + for (int j = 0; j < bt->mindeg; j++) 2.170 z->child[j] = y->child[j + bt->mindeg]; 2.171 } 2.172 2.173 - // Update y's nkeys. We don't bother NULLing out the now unused key and data pointers. 2.174 + // Update y's nkeys. 2.175 y->nkeys = bt->mindeg - 1; 2.176 2.177 // Make a hole in x's child list for the new node z. 2.178 - for (int j = x->nkeys; j > i; j--) 2.179 + for (int j = x->nkeys; j >= i + 1; j--) 2.180 x->child[j+1] = x->child[j]; 2.181 - x->child[i] = z; 2.182 + x->child[i+1] = z; 2.183 2.184 // Make a hole in x's key list for the new node z. 2.185 - for (int j = x->nkeys - 1; j > i-1; j--) 2.186 + for (int j = x->nkeys - 1; j >= i; j--) 2.187 { 2.188 x->key[j+1] = x->key[j]; 2.189 x->data[j+1] = x->data[j]; 2.190 @@ -205,8 +265,16 @@ 2.191 x->key[i] = y->key[bt->mindeg-1]; 2.192 x->data[i] = y->data[bt->mindeg-1]; 2.193 2.194 + x->nkeys += 1; 2.195 2.196 - x->nkeys += 1; 2.197 + /* // NULL out the now unused key and data pointers in y. */ 2.198 + /* for (int j = bt->mindeg; j < (2*bt->mindeg - 1); j++) */ 2.199 + /* { */ 2.200 + /* y->key[j] = NULL; */ 2.201 + /* y->data[j] = NULL; */ 2.202 + /* y->child[j] = NULL; */ 2.203 + /* } */ 2.204 + /* y->child[2*bt->mindeg - 1] = NULL; */ 2.205 2.206 return z; 2.207 } 2.208 @@ -218,3 +286,41 @@ 2.209 2.210 } 2.211 2.212 +//////////////////////////////////////////////////////////////////////////////// 2.213 +void 2.214 +btree_mem_walk_inorder(struct btree_mem * bt, void (*f)(int, void *, void *)) 2.215 + { 2.216 + btree_mem_node_walk_inorder(bt->root, f, 0); 2.217 + } 2.218 + 2.219 +//////////////////////////////////////////////////////////////////////////////// 2.220 +void 2.221 +btree_mem_node_walk_inorder(struct btree_mem_node * node, void (*f)(int, void *, void *), int depth) 2.222 + { 2.223 + 2.224 + // for (int i = 0; i < depth; i++) 2.225 + // printf("\t"); 2.226 + // printf("nkeys %d\n", node->nkeys); 2.227 + // printf("walking\n"); 2.228 + if (0 == node->nkeys) 2.229 + { 2.230 + // printf("no keys\n"); 2.231 + if (NULL != node->child[0]) 2.232 + { 2.233 + // printf(": walking child\n"); 2.234 + btree_mem_node_walk_inorder(node->child[0], f, depth+1); 2.235 + } 2.236 + return; 2.237 + } 2.238 + 2.239 + // printf("walking %d keys\n", node->nkeys); 2.240 + for (int i = 0; i < node->nkeys; i++) 2.241 + { 2.242 + if (! node->leaf) 2.243 + btree_mem_node_walk_inorder(node->child[i], f, depth+1); 2.244 + f(depth, node->key[i], node->data[i]); 2.245 + } 2.246 + if (! node->leaf) 2.247 + btree_mem_node_walk_inorder(node->child[node->nkeys], f, depth+1); 2.248 + } 2.249 +
3.1 --- a/src/btree_mem.h Tue Oct 16 19:57:23 2012 -0500 3.2 +++ b/src/btree_mem.h Wed Oct 17 02:17:47 2012 -0500 3.3 @@ -18,4 +18,6 @@ 3.4 void * btree_mem_find(struct btree_mem * bt, void * key); 3.5 void * btree_mem_remove(struct btree_mem * bt, void * key); 3.6 3.7 +void btree_mem_walk_inorder(struct btree_mem * bt, void (*f)(int, void *, void *)); 3.8 + 3.9 #endif
4.1 --- a/src/btree_mem_test.c Tue Oct 16 19:57:23 2012 -0500 4.2 +++ b/src/btree_mem_test.c Wed Oct 17 02:17:47 2012 -0500 4.3 @@ -10,14 +10,50 @@ 4.4 return strcmp(a, b); 4.5 } 4.6 4.7 + 4.8 +void 4.9 +print_data(int depth, void * key, void * data) 4.10 + { 4.11 + for (int i = 0; i < depth; i++) 4.12 + printf("\t"); 4.13 + printf("%d %s\n", *((int*)key), (char *) data); 4.14 + } 4.15 + 4.16 +void 4.17 +print_tree(struct btree_mem * bt) 4.18 + { 4.19 + printf("==================================\n"); 4.20 + btree_mem_walk_inorder(bt, print_data); 4.21 + printf("==================================\n"); 4.22 + } 4.23 + 4.24 int 4.25 main(int argc, char ** argv) 4.26 { 4.27 - struct btree_mem * bt = btree_mem_new(2, cmp); 4.28 +#define MINDEGREE 3 4.29 + struct btree_mem * bt = btree_mem_new(MINDEGREE, cmp); 4.30 if (NULL == bt) 4.31 { 4.32 fprintf(stderr, "Unable to create new btree_mem\n"); 4.33 exit(EXIT_FAILURE); 4.34 } 4.35 + 4.36 +#define MAXKEYS 20 4.37 + int keys[MAXKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 4.38 + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; 4.39 + char * data[MAXKEYS] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", 4.40 + "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; 4.41 + 4.42 + for (int i = 0; i < MAXKEYS; i++) 4.43 + { 4.44 + print_tree(bt); 4.45 + if (NULL == btree_mem_insert(bt, keys+i, data[i])) 4.46 + { 4.47 + fprintf(stderr, "btree_mem_insert failed\n"); 4.48 + exit(EXIT_FAILURE); 4.49 + } 4.50 + } 4.51 + print_tree(bt); 4.52 + 4.53 exit(EXIT_SUCCESS); 4.54 }