我有一个边缘列表格式的巨大图形,其中字符串作为节点标签。我想知道将字符串映射到整数的“最佳”方法是什么。输入文件遵循以下示例:
Mike Andrew
Mike Jane
John Jane
输出(即映射文件)应为:
1 2
1 3
4 3
下面粘贴的是C语言中的框架,该框架读取输入文件。有人可以建议我该怎么做。
#include <stdio.h>
int LoadFile(const char * filename) {
FILE *fp = NULL;
char node1[10];
char node2[10];
int idx = 0;
fp = fopen(filename, "r");
if (fp == NULL) {
perror("Error");
}
while (fscanf(fp, "%s %s", &node1, &node2) == 2) {
idx++;
}
fclose(fp);
return idx;
}
int main(void) {
int n = LoadFile("./test.txt");
printf("Number of edges: %d\n", n);
return 0;
}
答案 0 :(得分:2)
您需要天真的地图实现(将字符串映射为整数)。
定义如下的结构以存储字符串。
typedef struct {
unsigned int hashed;
char **map;
} hash;
定义一个函数,该函数将在不存在字符串的情况下将其插入到哈希图中,并返回哈希图中的字符串索引。
int insertInMap(hash *map, char *entry)
将返回的索引存储到edge
结构中。
edges[i].first =insertInMap(&map,first_string);
edges[i].second =insertInMap(&map,second_string)
示例代码:
typedef struct {
unsigned int first;
unsigned int second;
} edge;
typedef struct {
unsigned int hashed;
char **map;
} hash;
int insertInMap(hash *map, char *entry)
{
int i =0;
for (i=0;i<map->hashed;i++)
{
if (strcmp(map->map[i],entry) == 0)
return i+1;
}
/* Warning no boundary check is added */
map->map[map->hashed++] = strdup(entry);
return map->hashed;
}
edge *LoadFile(const char * filename) {
FILE *fp = NULL;
char node1[10];
char node2[10];
int idx = 0;
edge *edges;
hash map;
int numEdges = 10;
edges = malloc( numEdges * sizeof(edge));
map.map = malloc(numEdges * sizeof(char*));
map.hashed = 0;
fp = fopen(filename, "r");
if (fp == NULL) {
perror("Error");
}
while (fscanf(fp, "%s %s", &node1, &node2) == 2) {
if (idx >= numEdges)
{
numEdges *=2;
edges = realloc(edges, numEdges * sizeof(edge));
map.map = realloc(map.map, numEdges * sizeof(char*));
}
edges[idx].first =insertInMap(&map,node1);
edges[idx].second =insertInMap(&map,node2);
idx++;
}
fclose(fp);
return edges;
}
稍后打印edges
。
答案 1 :(得分:1)
我建议您使用Trie数据结构。它旨在存储单词并为它们关联一个值。
相对于哈希图,特里树的优点如下:
在trie中,内存使用通常比在哈希表中低,但是在最坏的情况下,它将使用更多的内存。
DAWG (或确定性非循环有限状态自动机)为此目的提供了更为有效的数据结构,但是它的构造要复杂得多,因此,如果您的图形中没有数百万个节点, d建议您坚持使用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';
}
在字符串中插入一个字符串/值对
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);
}
在特里搜索值:
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));
}