我建议您使用Trie 数据结构。它旨在存储单词并将它们关联一个值。
trie 相对于 hashmap 的优势如下:
- 查找元素更快
- 没有冲突
- 遍历 trie 或按字母顺序返回所有值的简单方法
- 直接实现(无哈希函数,无链表...)。这是一棵简单的树。
trie 的内存使用量通常低于哈希表,但在最坏的情况下会使用更多的内存。
为此目的,一个更有效的数据结构是DAWG (或确定性非循环有限状态自动机),但它的构造要复杂得多,所以如果你的图中没有数百万个节点,我建议你坚持 Trie。
C 中可能的实现如下:
数据结构:
#include <stdlib.h>
#include <stdio.h>
#define ALPHABET_SIZE 26
#define IMPOSSIBLE_VALUE -42
typedef struct TrieNode_struct {
struct TrieNode_struct *children[ALPHABET_SIZE];
int value;
} TrieNode_t;
typedef TrieNode_t *Trie_t;
TrieNode_t *new_node() {
TrieNode_t *new_node = malloc(sizeof(TrieNode_t));
new_node->value = IMPOSSIBLE_VALUE;
for (int i = 0; i < ALPHABET_SIZE; i++) {
new_node->children[i] = NULL;
}
return new_node;
}
int char_to_idx(char c){
return c - 'a';
}
在 trie 中插入字符串/值对
void trie_insert_rec(TrieNode_t *node, char *str, int val, int depth) {
if (str[depth] == '\0') {
node->value = val;
} else {
if (node->children[char_to_idx(str[depth])] == NULL) {
node->children[char_to_idx(str[depth])] = new_node();
}
trie_insert_rec(node->children[char_to_idx(str[depth])], str, val, depth+1);
}
}
void trie_insert(Trie_t trie, char *str, int val) {
trie_insert_rec(trie, str, val, 0);
}
在 trie 中搜索一个值:
int trie_fetch_rec(TrieNode_t *node, char *str, int depth) {
if (str[depth] == '\0') {
return node->value;
} else if (node->children[char_to_idx(str[depth])] == NULL) {
return IMPOSSIBLE_VALUE;
} else {
return trie_fetch_rec(node->children[char_to_idx(str[depth])], str, depth+1);
}
}
int trie_fetch(TrieNode_t *node, char *str){
return trie_fetch_rec(node, str, 0);
}
小玩具测试
int main() {
Trie_t trie = new_node();
char str[5] = "john\0";
trie_insert(trie, str, 11);
printf("%d\n", trie_fetch(trie, str));
}