将带有字符串节点标签的边列表映射到整数标签
Map edgelist with string node labels to integer labels
我有一个边列表格式的巨大图,其中字符串作为节点标签。我想知道将字符串映射到整数的 "best" 方法是什么。输入文件如下示例:
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;
}
您需要映射的简单实现(将字符串映射到整数)。
定义一个结构体来存储字符串。
typedef struct {
unsigned int hashed;
char **map;
} hash;
定义一个函数,如果字符串不存在则将其插入到 hashmap 中,并且 return 字符串在 hashmap 中的索引。
int insertInMap(hash *map, char *entry)
将 returned 索引存储到 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
。
我建议您使用 Trie 数据结构。它旨在存储单词并将它们关联到一个值。
trie 相对于 hashmap 的优点如下:
- 查找元素更快
- 没有碰撞
- 按字母顺序遍历 trie 或 return 所有值的简单方法
- Straight-forward 实现(没有散列函数,没有链表......)。这是一棵简单的树。
trie 中的内存使用通常低于哈希 table,但在最坏的情况下它会使用更多内存。
用于此目的的更有效的数据结构是 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 中插入 string/value 对
void trie_insert_rec(TrieNode_t *node, char *str, int val, int depth) {
if (str[depth] == '[=11=]') {
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] == '[=12=]') {
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);
}
小toy-test
int main() {
Trie_t trie = new_node();
char str[5] = "john[=13=]";
trie_insert(trie, str, 11);
printf("%d\n", trie_fetch(trie, str));
}
我有一个边列表格式的巨大图,其中字符串作为节点标签。我想知道将字符串映射到整数的 "best" 方法是什么。输入文件如下示例:
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;
}
您需要映射的简单实现(将字符串映射到整数)。
定义一个结构体来存储字符串。
typedef struct { unsigned int hashed; char **map; } hash;
定义一个函数,如果字符串不存在则将其插入到 hashmap 中,并且 return 字符串在 hashmap 中的索引。
int insertInMap(hash *map, char *entry)
将 returned 索引存储到
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
。
我建议您使用 Trie 数据结构。它旨在存储单词并将它们关联到一个值。
trie 相对于 hashmap 的优点如下:
- 查找元素更快
- 没有碰撞
- 按字母顺序遍历 trie 或 return 所有值的简单方法
- Straight-forward 实现(没有散列函数,没有链表......)。这是一棵简单的树。
trie 中的内存使用通常低于哈希 table,但在最坏的情况下它会使用更多内存。
用于此目的的更有效的数据结构是 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 中插入 string/value 对
void trie_insert_rec(TrieNode_t *node, char *str, int val, int depth) {
if (str[depth] == '[=11=]') {
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] == '[=12=]') {
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);
}
小toy-test
int main() {
Trie_t trie = new_node();
char str[5] = "john[=13=]";
trie_insert(trie, str, 11);
printf("%d\n", trie_fetch(trie, str));
}