aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Hörnquist <hugo@lysator.liu.se>2019-01-22 11:41:52 +0100
committerHugo Hörnquist <hugo@lysator.liu.se>2019-01-22 11:41:52 +0100
commiteb823898c385bb3a58c9641a988e6260a7d45176 (patch)
tree8bfa8f50ecd5c453dae771db2489aa2be97bef36
parentReplace some stack allocations with SNEW. (diff)
downloadcalp-eb823898c385bb3a58c9641a988e6260a7d45176.tar.gz
calp-eb823898c385bb3a58c9641a988e6260a7d45176.tar.xz
Add trie data structure.
-rw-r--r--trie.c1
-rw-r--r--trie.h49
-rw-r--r--trie.inc110
3 files changed, 160 insertions, 0 deletions
diff --git a/trie.c b/trie.c
new file mode 100644
index 00000000..aa83f622
--- /dev/null
+++ b/trie.c
@@ -0,0 +1 @@
+#include "trie.h"
diff --git a/trie.h b/trie.h
new file mode 100644
index 00000000..9d8b1ec0
--- /dev/null
+++ b/trie.h
@@ -0,0 +1,49 @@
+#ifndef TRIE_H
+#define TRIE_H
+
+#include "macro.h"
+
+#define TRIE(T) TP(trie__, T)
+#define TRIE_NODE(T) TP(trie_node__, T)
+
+#define TRIE_INIT(T) CONSTRUCTOR_GEN(trie, T, 0)
+#define TRIE_NODE_INIT(T) CONSTRUCTOR_GEN(trie_node, T, 0)
+
+#define TRIE_FREE(T) TP(trie_free__, T)
+#define TRIE_NODE_FREE(T) TP(trie_node_free__, T)
+
+#define TRIE_PUT(T) TP(trie_put__, T)
+#define TRIE_GET(T) TP(trie_get__, T)
+
+#endif /* TRIE_H */
+#ifdef TYPE
+
+typedef struct TRIE_NODE(TYPE) {
+ char c;
+ TYPE* value;
+ struct TRIE_NODE(TYPE)* next;
+ /* child == NULL means leaf? */
+ struct TRIE_NODE(TYPE)* child;
+} TRIE_NODE(TYPE);
+
+typedef struct {
+ TRIE_NODE(TYPE)* root;
+} TRIE(TYPE);
+
+
+int CONSTRUCTOR_DECL ( TRIE(TYPE) );
+
+int CONSTRUCTOR_DECL (TRIE_NODE(TYPE), char c);
+
+int CONSTRUCTOR_DECL (TRIE_NODE(TYPE),
+ char c, TRIE_NODE(TYPE)* next, TRIE_NODE(TYPE)* child );
+
+int TRIE_PUT(TYPE) ( TRIE(TYPE)* trie, char* key, TYPE* val );
+
+TYPE* TRIE_GET(TYPE) ( TRIE(TYPE)* trie, char* key );
+
+int TRIE_NODE_FREE(TYPE) ( TRIE_NODE(TYPE)* node );
+
+int TRIE_FREE(TYPE) ( TRIE(TYPE)* trie );
+
+#endif /* TYPE */
diff --git a/trie.inc b/trie.inc
new file mode 100644
index 00000000..96765c2f
--- /dev/null
+++ b/trie.inc
@@ -0,0 +1,110 @@
+#ifndef TYPE
+#error "Set TYPE before including this file"
+#else
+
+#include "err.h"
+
+int TRIE_INIT(TYPE) ( TRIE(TYPE)* trie ) {
+ NEW(TRIE_NODE(TYPE), t, '\0');
+ trie->root = t;
+ return 0;
+}
+
+int CONSTRUCTOR_DECL (TRIE_NODE(TYPE), char c) {
+ this->c = c;
+ this->next = NULL;
+ this->child = NULL;
+ return 0;
+}
+
+// int TRIE_NODE_INIT(TYPE) (
+// TRIE_NODE(TYPE)* node,
+int CONSTRUCTOR_DECL (TRIE_NODE(TYPE),
+ char c,
+ TRIE_NODE(TYPE)* next,
+ TRIE_NODE(TYPE)* child )
+{
+ this->c = c;
+ this->next = next;
+ this->child = child;
+ return 0;
+}
+
+int TRIE_PUT(TYPE) ( TRIE(TYPE)* trie, char* key, TYPE* val ) {
+ TRIE_NODE(TYPE) *cur, *last;
+
+ last = trie->root;
+ cur = last->child;
+
+ char* subkey = key;
+ // --------------------------------------------------
+
+ while (1) {
+ if (cur == NULL) {
+ /* Build direct LL for remaining subkey */
+ for (char* c = subkey; c[0] != '\0'; c++) {
+ NEW(TRIE_NODE(TYPE), t, *c);
+ last->child = t;
+ last = t;
+ }
+ last->value = val;
+ return 0;
+ } else if (cur->c == subkey[0]) {
+ /* This node belongs to the key,
+ * Decend further */
+ last = cur;
+ cur = cur->child;
+ subkey++;
+ } else if (subkey[0] == '\0') {
+ /* Key finished */
+ last->value = val;
+ return 0;
+ } else if (cur->next != NULL) {
+ /* This node was not part of the set, but it's sibling might */
+ cur = cur->next;
+ /* `last` not set since we aren't moving down */
+ } else {
+ /* No node on this level was part of the set, create a new
+ * sibling and follow down that parse */
+ NEW(TRIE_NODE(TYPE), t, *subkey);
+ cur->next = t;
+ last = cur;
+ cur = t;
+ }
+ }
+
+ return 0;
+}
+
+TYPE* TRIE_GET(TYPE) ( TRIE(TYPE)* trie, char* key ) {
+ TRIE_NODE(TYPE)* n = trie->root->child;
+ char* subkey = key;
+
+ while (n != NULL) {
+ if (subkey[1] == '\0') {
+ return n->value;
+ } else if (subkey[0] == n->c) {
+ n = n->child;
+ subkey++;
+ } else {
+ n = n->next;
+ }
+ }
+
+ ERR("Position not found");
+ return 0;
+}
+
+int TRIE_NODE_FREE(TYPE) ( TRIE_NODE(TYPE)* node ) {
+ if (node == NULL) return 0;
+ if (node->value != NULL) free (node->value);
+ if (node->next != NULL) TRIE_NODE_FREE(TYPE)(node->next);
+ if (node->child != NULL) TRIE_NODE_FREE(TYPE)(node->child);
+ return 0;
+}
+
+int TRIE_FREE(TYPE) ( TRIE(TYPE)* trie ) {
+ return TRIE_NODE_FREE(TYPE)(trie->root);
+}
+
+#endif /* TYPE */