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.