我正在编辑一个trie程序,将我自己的字符串输入到trie中。当我传递像"hello"这样的常量时,没有分段错误的情况,但是当我传递一个字符串变量时,它会出现分段错误(核心转储)。 这是功能:-
void insert(struct Trie *head, char* str)//FUNCTION CONCERNED WITH SEGMENTATION FAULT POSSIBLY OTHERS
{
// 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++;
}
考虑
struct Trie *head=(struct Trie*)malloc(sizeof(struct Trie));
insert(head,"hello");
这很好 但是如果我为字符串(输入)赋值并传递它
char str[100];
scanf("%s",str);
insert(head,str);
这会产生 SEG 故障。(插入功能,不是扫描) 我不擅长调试段错误,所以我想得到一些帮助,说明为什么会这样。我该如何纠正它 下面的完整代码供参考(完全向下滚动到主函数)
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<ctype.h>
// define character size
#define CHAR_SIZE 26
// A Trie node
struct Trie
{
int isLeaf; // 1 when node is a leaf node
struct Trie* character[CHAR_SIZE];
};
// 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;
}
// Iterative function to insert a string in Trie
void insert(struct Trie *head, char* str)//FUNCTION CONCERNED WITH SEGMENTATION FAULT POSSIBLY OTHERS
{
// 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++;
}
// 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;
}
// returns 1 if given node has any children
int haveChildren(struct Trie* curr)
{
for (int i = 0; i < CHAR_SIZE; i++)
if (curr->character[i])
return 1; // child found
return 0;
}
// Recursive function to delete a string in Trie
int deletion(struct Trie **curr, char* str)
{
// return if Trie is empty
if (*curr == NULL)
return 0;
// if we have not reached the end of the string
if (*str)
{
// recur for the node corresponding to next character in
// the string and if it returns 1, delete current node
// (if it is non-leaf)
if (*curr != NULL && (*curr)->character[*str - 'a'] != NULL &&
deletion(&((*curr)->character[*str - 'a']), str + 1) &&
(*curr)->isLeaf == 0)
{
if (!haveChildren(*curr))
{
free(*curr);
(*curr) = NULL;
return 1;
}
else {
return 0;
}
}
}
// if we have reached the end of the string
if (*str == ' ' && (*curr)->isLeaf)
{
// if current node is a leaf node and don't have any children
if (!haveChildren(*curr))
{
free(*curr); // delete current node
(*curr) = NULL;
return 1; // delete non-leaf parent nodes
}
// if current node is a leaf node and have children
else
{
// mark current node as non-leaf node (DON'T DELETE IT)
(*curr)->isLeaf = 0;
return 0; // don't delete its parent nodes
}
}
return 0;
}
// Trie Implementation in C - Insertion, Searching and Deletion
int main()
{
struct Trie* head = getNewTrieNode();
insert(head, "hello");
printf("%d ", search(head, "hello")); // print 1
insert(head, "helloworld");
printf("%d ", search(head, "helloworld")); // print 1
printf("%d ", search(head, "helll")); // print 0 (Not present)
insert(head, "hell");
printf("%d ", search(head, "hell")); // print 1
insert(head, "h");
printf("%d n", search(head, "h")); // print 1 + newline
deletion(&head, "hello");
printf("%d ", search(head, "hello")); // print 0 (hello deleted)
printf("%d ", search(head, "helloworld")); // print 1
printf("%d n", search(head, "hell")); // print 1 + newline
deletion(&head, "h");
printf("%d ", search(head, "h")); // print 0 (h deleted)
printf("%d ", search(head, "hell")); // print 1
printf("%dn", search(head, "helloworld")); // print 1 + newline
deletion(&head, "helloworld");
printf("%d ", search(head, "helloworld")); // print 0
printf("%d ", search(head, "hell")); // print 1
deletion(&head, "hell");
printf("%dn", search(head, "hell")); // print 0 + newline
if (head == NULL)
printf("Trie empty!!n"); // Trie is empty now
printf("%d ", search(head, "hell")); // print 0
//HERE IS WHERE THE SEGMENTATION FAULT ISSUE STARTS
char str[100];
int i=0;
scanf("%s",str);
for(i=0;i<strlen(str);i++)
str[i]=tolower(str[i]);
puts(str);
//SEGMENTATION FAULT OCCURS IN LINE BELOW
insert(head,str);
}
```:
从 trie 中删除最后一个字符串时,将删除其所有祖先,包括根节点。这使head
为空。然后,将head
传递给取消引用它的insert
。
您可以安排不删除根节点(并更改检测空 trie 的方式),但解决此问题的另一种方法是使insert
除了中间节点之外自动激活根节点。
void insert(struct Trie **curr, const char* str) {
while (1) {
if (!*curr)
*curr = getNewTrieNode();
if (!*str)
break;
curr = &( curr->character[*str - 'a'] );
++str;
}
(*curr)->isLeaf = 1;
}
这将允许您替换
struct Trie* head = getNewTrieNode();
跟
struct Trie* head = NULL;