插入二叉树时出现分段错误

时间:2015-02-21 17:31:18

标签: c pointers segmentation-fault

我无法弄清楚如何正确运行,给出了分段错误。一段代码如下。你也可以看一下头,我不确定它是否是在另一个文件中初始化为null的正确方法,它运行如下:

Table tb ;
tb= initialise_table (table_size); 
tb = insert(text_words,tb);

//these 3 typedef declarations are in a "some.h" file       
typedef struct node * tree_ptr; 
typedef char* Key_Type; 
typedef struct table* Table;  
struct node { 
    Key_Type element; 
    tree_ptr left; 
    tree_ptr right; 
}; 

struct table { 
    tree_ptr head; 
};

Table init_table()  {

   Table head = NULL;

} 
Table insert(Key_Type key ,Table  temp )  {
    tree_ptr t = (tree_ptr)malloc(sizeof(tree_ptr));
    t->element = key;
    // t->left = t->right = NULL;
    if (temp->head==NULL) {
        temp = (Table)malloc (sizeof (Table)); 
        temp->head = t;
        printf("empty tree ");
    }    
    else {          
        temp = insert(t->element,temp);
        printf("inserted into "); 
    }

    return temp;   
    printf("wowo!");
}

2 个答案:

答案 0 :(得分:1)

主要问题在于代码,您可以使用它来调用函数:

Table tb;

tb = insert(text_words, tb);

您有一个未初始化的指针tb,您将其传递给该函数。在函数内部,你有:

Table insert(Key_Type key, Table temp)
{
    tree_ptr t = (tree_ptr)malloc(sizeof(*t));  // Fixed size
    t->element = key;
    // t->left = t->right = NULL;
    if (temp->head==NULL)
    {

因此,您正在访问(取消引用)未定义的指针,并且您的程序正在崩溃。

我认为你应该使用table_init()初始化你的表,但该功能实际上没有任何帮助。它定义并初始化一个局部变量,但即使承诺这样做也不会返回任何内容。

请参阅Is it a good idea to typedef pointers?简短的回答是'不,这通常不是一个好主意'。

即使你修改了这样的调用代码,你仍然会遇到问题(一个必要但不充分的步骤):

Table tb = NULL;
tb = insert(text_words, tb);

或者也许:

Table tb = init_table();
tb = insert(text_words, tb);

但您需要init_table()的认真升级版本,例如:

Table init_table(void)
{
   Table root = malloc(sizeof(*head));
   root->head = NULL;
   return root;
}

insert()中的代码需要确保它不会取消引用空指针(而不是不确定的指针)。

Table insert(Key_Type key, Table root)
{
    tree_ptr t = (tree_ptr)malloc(sizeof(*t));  // Fixed size
    t->element = key;
    t->left = t->right = NULL;
    if (root == NULL)
    {
        root = init_table();
        root->head = t;
    }
    else
    {
        …
    }
    return root;
}

鉴于Key_Type伪装成char *,您可能需要查看如何在树结构中保存密钥;您可能需要使用strdup()来复制数据。如果没有看到你如何管理传递给insert()函数的字符串,就不可能肯定地说。如果调用代码确保每次都传递新指针,则可以保存指针。 OTOH,如果每次传递相同的指针,你肯定需要复制数据,使用strdup()是一种明智的方法。请注意,strdup()是POSIX的标准;它不是标准C的一部分。

答案 1 :(得分:0)

这是一个主要问题:

tree_ptr t = (tree_ptr) malloc(sizeof(tree_ptr));

应该是:

tree_ptr t = (tree_ptr) malloc(sizeof(struct node));

您的代码实际上没有进行任何二进制搜索。实际上,它只是无限地递归创建新节点。尝试更像这样的东西:

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

typedef struct Node
{ 
  char        *element; 
  struct Node *left; 
  struct Node *right; 

} Node;

typedef struct
{
  Node  *root;
  size_t size;

} Tree;

void  Tree_init(Tree *t);
Node *Tree_insert(Tree *t, const char *key);
void  Tree_insert_r(Node *subtree, Node *n, size_t size);
void  Tree_pre_order_r(Node *subtree);

void Tree_init(Tree *t)
{
  t->root = NULL;
  t->size = 0;
}    

Node *Tree_insert(Tree *t, const char *key)
{
  Node *ret = (Node*) malloc(sizeof(Node));

  if (ret)
  {
    ret->left = ret->right = NULL;

    if ((ret->element = strdup(key)))  /* make a copy of key */
    {
      if (NULL != t->root)
        Tree_insert_r(t->root, ret, t->size);
      else
        t->root = ret;

      ++t->size;
    }
    else
    {
      free(ret);
      ret = NULL;
    }
  }

  return ret;
}

void Tree_insert_r(Node *subtree, Node *n, size_t size)
{
  int cmp = strcmp(n->element, subtree->element);

  if (cmp < 0 || (cmp == 0 && size % 2 == 0))
  {
    if (NULL != subtree->left)
      subtree = subtree->left;
    else
    {
      subtree->left = n;
      return;
    }
  }
  else
  {
    if (NULL != subtree->right)
      subtree = subtree->right;
    else
    {
      subtree->right = n;
      return;
    }    
  }

  Tree_insert_r(subtree, n, size);
}

void Tree_pre_order_r(Node *subtree)
{
  if (NULL == subtree)
    return;

  fprintf(stdout, "'%s'\n", subtree->element);

  Tree_pre_order_r(subtree->left);
  Tree_pre_order_r(subtree->right);
}

int main()
{
  Tree t;

  Tree_init(&t);
  Tree_insert(&t, "Hello");
  Tree_insert(&t, "World!");
  Tree_insert(&t, "etc.");

  Tree_pre_order(t.root);

  return 0;
}