github.com/moontrade/nogc@v0.1.7/collections/btree/README.md (about) 1 # btree.c 2 3 A B-tree implementation in C. 4 5 ## Features 6 7 - Generic interface with support for variable sized items. 8 - Fast sequential bulk loading 9 - ANSI C (C99) 10 - Supports custom allocators 11 - Pretty darn good performance. 🚀 12 13 ## Example 14 15 ```c 16 #include <stdio.h> 17 #include <string.h> 18 #include "btree.h" 19 20 struct user { 21 char *first; 22 char *last; 23 int age; 24 }; 25 26 int user_compare(const void *a, const void *b, void *udata) { 27 const struct user *ua = a; 28 const struct user *ub = b; 29 int cmp = strcmp(ua->last, ub->last); 30 if (cmp == 0) { 31 cmp = strcmp(ua->first, ub->first); 32 } 33 return cmp; 34 } 35 36 bool user_iter(const void *a, void *udata) { 37 const struct user *user = a; 38 printf("%s %s (age=%d)\n", user->first, user->last, user->age); 39 return true; 40 } 41 42 int main() { 43 // create a new btree where each item is a `struct user`. 44 struct btree *tr = btree_new(sizeof(struct user), 0, user_compare, NULL); 45 46 // load some users into the btree. Each set operation performas a copy of 47 // the data that is pointed to in the second argument. 48 btree_set(tr, &(struct user){ .first="Dale", .last="Murphy", .age=44 }); 49 btree_set(tr, &(struct user){ .first="Roger", .last="Craig", .age=68 }); 50 btree_set(tr, &(struct user){ .first="Jane", .last="Murphy", .age=47 }); 51 52 struct user *user; 53 54 printf("\n-- get some users --\n"); 55 user = btree_get(tr, &(struct user){ .first="Jane", .last="Murphy" }); 56 printf("%s age=%d\n", user->first, user->age); 57 58 user = btree_get(tr, &(struct user){ .first="Roger", .last="Craig" }); 59 printf("%s age=%d\n", user->first, user->age); 60 61 user = btree_get(tr, &(struct user){ .first="Dale", .last="Murphy" }); 62 printf("%s age=%d\n", user->first, user->age); 63 64 user = btree_get(tr, &(struct user){ .first="Tom", .last="Buffalo" }); 65 printf("%s\n", user?"exists":"not exists"); 66 67 68 printf("\n-- iterate over all users --\n"); 69 btree_ascend(tr, NULL, user_iter, NULL); 70 71 printf("\n-- iterate beginning with last name `Murphy` --\n"); 72 btree_ascend(tr, &(struct user){.first="",.last="Murphy"}, user_iter, NULL); 73 74 btree_free(tr); 75 } 76 77 // output: 78 // -- get some users -- 79 // Jane age=47 80 // Roger age=68 81 // Dale age=44 82 // not exists 83 // 84 // -- iterate over all users -- 85 // Roger Craig (age=68) 86 // Dale Murphy (age=44) 87 // Jane Murphy (age=47) 88 // 89 // -- iterate beginning with last name `Murphy` -- 90 // Dale Murphy (age=44) 91 // Jane Murphy (age=47) 92 ``` 93 94 ## Functions 95 96 ### Basic 97 98 ```sh 99 btree_new # allocate a new btree 100 btree_free # free the btree 101 btree_count # number of items in the btree 102 btree_set # insert or replace an existing item and return the previous 103 btree_get # get an existing item 104 btree_delete # delete and return an item 105 ``` 106 107 ### Iteration 108 109 ```sh 110 btree_ascend # iterate over items in ascending order starting at pivot point. 111 btree_descend # iterate over items in descending order starting at pivot point. 112 ``` 113 114 ### Queues 115 116 ```sh 117 btree_pop_min # remove and return the first item in the btree 118 btree_pop_max # remove and return the last item in the btree 119 btree_min # return the first item in the btree 120 btree_max # return the last item in the btree 121 ``` 122 123 ### Bulk loading 124 125 ```sh 126 btree_load # same as btree_set but optimized for fast loading, 10x boost. 127 ``` 128 129 ## Testing and benchmarks 130 131 ```sh 132 $ cc -DBTREE_TEST btree.c && ./a.out # run tests 133 $ cc -DBTREE_TEST -O3 btree.c && BENCH=1 ./a.out # run benchmarks 134 ``` 135 136 The following benchmarks were run on my 2019 Macbook Pro (2.4 GHz 8-Core Intel Core i9) using gcc-9. 137 The items are simple 4-byte ints. 138 139 ``` 140 load (seq) 1000000 ops in 0.010 secs, 10 ns/op, 98000784 op/sec, 6.92 bytes/op, 0.01 allocs/op 141 set (seq) 1000000 ops in 0.069 secs, 69 ns/op, 14459434 op/sec, 8.29 bytes/op, 0.01 allocs/op 142 get (seq) 1000000 ops in 0.065 secs, 65 ns/op, 15369010 op/sec 143 load (rand) 1000000 ops in 0.212 secs, 212 ns/op, 4718740 op/sec, 5.94 bytes/op, 0.01 allocs/op 144 set (rand) 1000000 ops in 0.175 secs, 175 ns/op, 5726065 op/sec, 5.88 bytes/op, 0.01 allocs/op 145 get (rand) 1000000 ops in 0.163 secs, 163 ns/op, 6125687 op/sec 146 delete (rand) 1000000 ops in 0.177 secs, 177 ns/op, 5644647 op/sec 147 set (seq-hint) 1000000 ops in 0.034 secs, 34 ns/op, 29140076 op/sec, 8.29 bytes/op, 0.01 allocs/op 148 get (seq-hint) 1000000 ops in 0.053 secs, 53 ns/op, 18774054 op/sec 149 min 1000000 ops in 0.001 secs, 1 ns/op, 709723208 op/sec 150 max 1000000 ops in 0.002 secs, 2 ns/op, 611995104 op/sec 151 pop-min 1000000 ops in 0.035 secs, 35 ns/op, 28408284 op/sec 152 pop-max 1000000 ops in 0.023 secs, 23 ns/op, 42607584 op/sec 153 ``` 154 155 ## License 156 157 btree.c source code is available under the MIT License.