【发布时间】:2018-08-26 20:59:56
【问题描述】:
我在 trie 数据结构上添加单词(每个节点的字符) - 根据我在网络上找到的实现正确地发生 -
http://www.techiedelight.com/trie-implementation-insert-search-delete/
虽然我想扩展它并添加一个包含一些基于单词的数据的列表,比如词频等。
现在,当在 trie 节点上添加第一个元素时,我遇到了列表指针的问题 - 在方法 append_posting_list 中 - 并获得 segmetation fault。
这是到目前为止的代码。
main.h
#ifndef TRIE_H
#define TRIE_H
#define CHAR_SIZE 26
typedef struct posting_list {
int doc_id;
int tf;
int df;
struct posting_list *next;
} posting_list_node ;
struct Trie
{
posting_list_node *p_node; // this will be the head of the posting list for every word;
int isLeaf; // 1 when node is a leaf node
struct Trie* character[CHAR_SIZE];
};
struct Trie* getNewTrieNode();
void insert(struct Trie* *head, char* str, int doc_id);
int search(struct Trie* head, char* str);
#endif //TRIE_H
main.c
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
int main(){
struct Trie* head = getNewTrieNode();
insert(&head, "hello", 1);
return 0;
}
// Function that returns a new Trie node
struct Trie* getNewTrieNode()
{
struct Trie* node = (struct Trie*)malloc(sizeof(struct Trie));
node->isLeaf = 0;
for (int i = 0; i < CHAR_SIZE; i++)
node->character[i] = NULL;
return node;
}
posting_list_node* get_mem(){
posting_list_node* p;
p = (posting_list_node *)malloc(sizeof(posting_list_node));
if (p == NULL){
printf("Memory allocation failed\n");
exit(EXIT_FAILURE);
}
return p;
}
void append_posting_list(int doc_id, posting_list_node **n){
posting_list_node *new, *q;
new = get_mem();
new->doc_id = doc_id;
new->tf = 1;
new->next = NULL;
// if new is the first element of the list
if(n == NULL) {
*n = new;
} else {
q = *n;
while( q->next!=NULL) {
q = q->next;
}
q->next = new;
}
}
// Iterative function to insert a string in Trie.
void insert(struct Trie* *head, char* str, int doc_id)
{
// start from root node
struct Trie* curr = *head;
while (*str)
{
// create a new node if path doesn't exists
if (curr->character[*str - 'a'] == NULL)
curr->character[*str - 'a'] = getNewTrieNode();
// go to next node
curr = curr->character[*str - 'a'];
// move to next character
str++;
}
// already found this word, increase frequency
if(curr->isLeaf) {
curr->p_node->tf += 1;
} else {
append_posting_list(doc_id, curr->p_node);
// mark current node as leaf
curr->isLeaf = 1;
}
}
// Iterative function to search a string in Trie. It returns 1
// if the string is found in the Trie, else it returns 0
int search(struct Trie* head, char* str)
{
// return 0 if Trie is empty
if (head == NULL)
return 0;
struct Trie* curr = head;
while (*str)
{
// go to next node
curr = curr->character[*str - 'a'];
// if string is invalid (reached end of path in Trie)
if (curr == NULL)
return 0;
// move to next character
str++;
}
// if current node is a leaf and we have reached the
// end of the string, return 1
return curr->isLeaf;
}
我真的被困在这里了。 任何建议将不胜感激。
【问题讨论】:
-
观察:如果你只有一个源文件 (
main.c) 你真的不需要自定义标题。您使用标头在不同的源文件之间传递信息。如果你有一个文件trie.c和main.c中的程序,那么让trie.h声明trie.c提供的服务,所以main.c可以使用它们是有意义的。如果你只有main.c,真的不需要头文件;一切都可以放在源文件中。有时,您只是为未来的多文件开发做准备;没关系。但是trie.h和trie.c可能比main.h更好。 -
insert函数假定str中的每个字符都是小写字母。这是一个非常糟糕的假设,因为您很快就会发现。同时,您应该在getNewTrieNode函数中将node->p_node初始化为NULL。 -
您对外壳的看法是正确的,但我已经考虑到这一点,这里的问题是解除阻塞并继续。不过还是谢谢。
标签: c pointers memory-management data-structures trie