Advertisement
Guest User

Untitled

a guest
Jul 16th, 2019
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.89 KB | None | 0 0
  1. #include <assert.h> // assert
  2. #include <stdlib.h> // calloc, free
  3.  
  4. /** A prefix tree
  5. * An efficient key-value storage with string keys
  6. *
  7. * There exist two type of nodes:
  8. * 1. node->symbol == 0 -> node where a key ended, has node->value
  9. * 2. node->symbol != 0 -> node representing a character in a key, has node->child
  10. *
  11. * Each node potentially has a node->next, which represents a node in the same
  12. * key position but with a different symbol
  13. */
  14. struct Trie {
  15. char symbol;
  16. struct Trie *next;
  17. union {
  18. void *value;
  19. struct Trie *child;
  20. };
  21. };
  22.  
  23. /** Create a new Trie struct
  24. * This function assumes NULL == 0, but that's probably true in every machine
  25. * I'm not sure it is true in C++ but eh
  26. */
  27. struct Trie *trie_new() {
  28. return calloc(1, sizeof(struct Trie));
  29. }
  30.  
  31. /** Walk through a Trie and call a function on every value
  32. * This *must* be used to free values
  33. *
  34. * Example:
  35. * struct Trie *trie = trie_new();
  36. *
  37. * int *x = malloc(sizeof *x);
  38. * *x = 1;
  39. * trie_set(trie, "a", x);
  40. *
  41. * int *y = malloc(sizeof *y);
  42. * *y = 2;
  43. * trie_set(trie, "b", y);
  44. *
  45. * assert(trie_get(trie, "a") == x);
  46. * assert(trie_get(trie, "b") == y);
  47. *
  48. * trie_foreach_value(struct Trie *root, free);
  49. * trie_free(trie);
  50. */
  51. void trie_foreach_value(struct Trie *root, void (*f)(void*)) {
  52. if (root == NULL) return;
  53. trie_foreach_value(root->next, f);
  54. if (root->symbol != 0) trie_foreach_value(root->child, f);
  55. else f(root->value);
  56. }
  57.  
  58. /** Free a Trie
  59. * This function does not try to free values, for that utilize
  60. * trie_foreach_value with a custom free function
  61. */
  62. void trie_free(struct Trie *root) {
  63. if (root == NULL) return;
  64. trie_free(root->next);
  65. if (root->symbol != 0) trie_free(root->child);
  66. free(root);
  67. }
  68.  
  69. /** Set a key to a value in a Trie
  70. * This function requires that `value != NULL` so that missing keys can return
  71. * NULL in `trie_get`
  72. *
  73. * It also requires that the key is non-empty (i.e. strlen(key) != 0) for ease
  74. * of implementation
  75. */
  76. void trie_set(struct Trie *root, const char *key, void *value) {
  77. assert(value != NULL);
  78. assert(*key != 0);
  79.  
  80. struct Trie *conductor = root;
  81.  
  82. /* For each character of the key */
  83. for (; *key != 0; ++key) {
  84. /* Find a suitable node at this level */
  85. for (;; conductor = conductor->next) {
  86. /* If there already is a node at this level with the key's current
  87. * character, just use that and move on to the next level */
  88. if (conductor->symbol == *key) {
  89. conductor = conductor->child;
  90. break;
  91. }
  92.  
  93. /* If we reach this case, it means there are no more nodes in the
  94. * current level */
  95. if (conductor->next == NULL) {
  96. /* So we create a new node and set it to be the last node's
  97. * successor */
  98. struct Trie *next = trie_new();
  99. next->symbol = *key;
  100. conductor->next = next;
  101. conductor = next;
  102.  
  103. /* Then we move on to the next level as usual */
  104. struct Trie *child = trie_new();
  105. conductor->child = child;
  106. conductor = child;
  107. break;
  108. }
  109. }
  110. }
  111.  
  112. /* When we're here, we're at the last character of the key and so we just
  113. * set the current node's value */
  114. conductor->value = value;
  115. }
  116.  
  117. /** Get a key's value in a Trie
  118. * This function returns NULL if a key is not present
  119. */
  120. void *trie_get(struct Trie *root, const char *key) {
  121. assert(*key != 0);
  122.  
  123. if (root == NULL) return NULL;
  124. struct Trie *conductor = root;
  125.  
  126. for (; *key != 0; ++key) {
  127. for (; conductor->symbol != *key; conductor = conductor->next) {
  128. if (conductor->next == NULL) return NULL;
  129. }
  130.  
  131. if (conductor->child == NULL) return NULL;
  132. conductor = conductor->child;
  133. }
  134.  
  135. return conductor->value;
  136. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement