【问题标题】:Binary Tree segmentation fault after implementing search function实现搜索功能后的二叉树分割错误
【发布时间】:2014-07-30 06:49:32
【问题描述】:

我正在尝试编写一个执行以下操作的程序

-read a file from std in
-read each line, and add each line to a binary tree
 *if name is already in binary tree,dont add the name to the tree again but update its count of repititions
-print out the binary tree

正在读取的文件看起来像

dylan
bob
dylan
randall
randall

所以当我打印出二叉树时,我希望它打印出来

bob 1
dylan 2
randall 2

我能够成功打印出名称,而不必担心重复。我已经注释掉了使我的程序混乱的代码块,这些代码块是与我的搜索功能交互的任何东西,我在事后添加了这些功能以处理重复。该代码构建了一个二叉树,每个“离开”是一个由 4 部分组成的结构,名称、计数以及指向左右子节点的指针。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct node {
    char* name;
    int count;
    struct node* left;
    struct node* right;
};

struct node* addNode(char* string);
void insert(struct node *root, char* stringgg);
void preorder(struct node *root);
int search(struct node* leaf,char* string2find);

int main()
{
    char buffer[20];
    struct node *root = NULL;

    while( fgets(buffer, sizeof(buffer), stdin) != NULL )
    {
        if(root == NULL)
            root = addNode(buffer);
        else

            insert(root,buffer);

    }
    preorder(root);

}

struct node* addNode(char* string)
{
    struct node *temp = malloc(sizeof(struct node));
    temp->name = malloc(strlen(string) + 1);
    strcpy(temp->name,string);

    temp->left = NULL;
    temp->right = NULL;
    return temp;
}

void insert(struct node *root, char* stringgg)
{
   /* int flag = 5;
    flag = search(root,stringgg);
    if(flag == 1)
        return; */

    if(strcmp(stringgg,root->name) < 0)
    {
        if(root->left == NULL)
            root->left = addNode(stringgg);
        else
            insert(root->left, stringgg);
    }
    else
    {
        if(root->right == NULL)
            root->right = addNode(stringgg);
        else
            insert(root->right,stringgg);
    }
}

/*int search(struct node* leaf,char* string2find)
{
    if(strcmp(string2find,leaf->name) == 0)
    {
        leaf->count = leaf->count + 1;
        return 1;
    }
    else if(strcmp(string2find,leaf->name) < 0)
    {
        return search(leaf->left,string2find);
    }
    else
    {
        return search(leaf->right,string2find);
    }
    return 0;

} */

void preorder(struct node *root)
{
    if(root == NULL)
        return;
    printf("%s",root->name);
    preorder(root->left);
    preorder(root->right);

}

上面的代码会打印出所有的名字,即使它们已经在树中了。我希望有人能够指出我的搜索功能错误,以便在打印时不会导致分段错误。可能的原因可能是我对返回函数的不当使用,如果标志 == 1,我试图返回主函数,这意味着找到匹配,所以不要添加节点。但是如果 flag 不等于 1 则找不到匹配项,请继续添加节点。

【问题讨论】:

  • 首先解决这个问题:在main() 函数中elseinsert(root,buffer); 之前有一个不必要的新行。确保它是可编译的代码。
  • 而且,虽然与手头的问题没有太大关系,但我想指出int main()不一定是Cint main(void)是!
  • 如何退出fgets 循环?
  • 当你在友好的本地调试器下运行它时发生了什么?
  • @WedaPashi:标准 (ISO/IEC 9899:2011) 在第 5.1.2.2.1 节中说程序启动:[main] 应定义为返回类型为 @987654333 @ 并且不带参数:int main(void) { /* ... */ } ... 或等效项。虽然我总是写int main(void)(因为我编译时使用了-Wstrict-prototypes-Wold-style-definition等GCC选项),但写int main()并没有错,因为这是一个没有参数的函数。作为其他函数的声明,int otherfunc(); 是错误的;它表示“没有关于参数的信息”,应该是int otherfunc(void);

标签: c segmentation-fault structure binary-tree


【解决方案1】:

主要

while( fgets(buffer, sizeof(buffer), stdin) != NULL ){
    char *p = strchr(buffer, '\n');
    if(p) *p=0;//remove '\n'

在添加节点

temp->count = 1;//initialize counter
return temp;

插入时

void insert(struct node *root, char* stringgg){
    int cmp_stat = strcmp(stringgg,root->name);

    if(cmp_stat == 0)
        root->count++;
    else if(cmp_stat < 0) {
        if(root->left == NULL)
            root->left = addNode(stringgg);
        else
            insert(root->left, stringgg);
    } else {
        if(root->right == NULL)
            root->right = addNode(stringgg);
        else
            insert(root->right,stringgg);
    }
}

预购

printf("%s %d\n",root->name, root->count);

【讨论】:

    【解决方案2】:

    错误在于搜索 empty 树中的第一个项目——你调用

        search(root, stringgg)
    

    rootNULL,所以在search() 你打电话

        strcmp(string2find, leaf->name)
    

    使用leaf == NULL 并且程序崩溃。

    治愈方法:不要在更新树之前搜索 ,而是搜索 TO 更新它。

    struct node* update(struct node* nd, const char* str)
    {
        int cmp;
    
        // (sub)tree is empty? - create a new node with cnt==1
        if(nd == NULL)
            return CreateNode(str);
    
        // test if the node found
        cmp = strcmp(str, nd->name);
    
        if(cmp == 0)          // YES
            nd->count ++;     // update the counter
        else if(cmp < 0)      // NO - search in a subtree
            nd->left  = update(nd->left,  str);
        else
            nd->right = update(nd->right, str);
    
        return nd;            // return the updated subtree
    }
    

    然后在main() 中你只需更新树并存储它:

        root = update(root, buffer);
    

    实际上,root 的值只会在第一次调用时更改一次,并且所有后续分配都不会更改其值。然而,这使代码更具可读性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-20
      • 2020-11-07
      • 2022-11-15
      • 2019-04-15
      • 1970-01-01
      • 2015-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多