-
Notifications
You must be signed in to change notification settings - Fork 30
/
trie.c
113 lines (99 loc) · 2.59 KB
/
trie.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* @file trie.c
* @author hutusi ([email protected])
* @brief Refer to trie.h
* @date 2019-08-11
*
* @copyright Copyright (c) 2019, hutusi.com
*
*/
#include "trie.h"
#include "compare.h"
#include "def.h"
#include "hash.h"
#include <stdlib.h>
static TrieNode *trie_new_node(char ch)
{
TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode));
node->data = ch;
node->ending = false;
node->children = hash_table_new(
hash_char,
char_equal,
free,
NULL); /** value will be freed in root's recursive free func. */
return node;
}
Trie *trie_new()
{
Trie *trie = (Trie *)malloc(sizeof(Trie));
trie->root = trie_new_node((char)0);
return trie;
}
static void trie_free_node_recursive(TrieNode *node)
{
if (node == NULL)
return;
HashTableEntity *iterator = hash_table_first_entity(node->children);
while (iterator != NULL) {
HashTableEntity *prev = iterator;
iterator = hash_table_next_entity(node->children, prev);
TrieNode *child = (TrieNode *)(prev->value);
trie_free_node_recursive(child);
}
hash_table_free(node->children);
free(node);
}
void trie_free(Trie *trie)
{
// free root node will free all nodes
trie_free_node_recursive(trie->root);
free(trie);
}
static char *trie_char_dup(char value)
{
char *dup = (char *)malloc(sizeof(char));
*dup = value;
return dup;
}
int trie_insert(Trie *trie, const char *str, unsigned int len)
{
TrieNode *rover = trie->root;
for (int i = 0; i < len; ++i) {
TrieNode *node = hash_table_get(rover->children, (void *)&(str[i]));
if (node == HASH_TABLE_VALUE_NULL) {
node = trie_new_node(str[i]);
hash_table_insert(rover->children, trie_char_dup(str[i]), node);
}
rover = node;
}
rover->ending = true;
return 0;
}
TrieNode *trie_last_node(const Trie *trie, const char *str, unsigned int len)
{
TrieNode *rover = trie->root;
for (int i = 0; i < len; ++i) {
TrieNode *node = hash_table_get(rover->children, (void *)&(str[i]));
if (node == HASH_TABLE_VALUE_NULL) {
return NULL;
}
rover = node;
}
return rover;
}
int trie_delete(Trie *trie, const char *str, unsigned int len)
{
TrieNode *last = trie_last_node(trie, str, len);
if (last != NULL) {
last->ending = false;
return 0;
} else {
return -1;
}
}
bool trie_include(const Trie *trie, const char *str, unsigned int len)
{
TrieNode *last = trie_last_node(trie, str, len);
return last != NULL && last->ending == true;
}