2013-07-08 4 views
0

Здесь я написал код, который вставляет числа в двоичное дерево. Но он дает ошибку ошибки сегментации. А также он говорит: «Примечание: ожидаемый" структура дерева *, но аргумент типа "структура узла *» в строке 8. Вот код: -Ошибка сегментации двоичного дерева

#include<stdio.h> 
#include<stdlib.h> 
struct tree{ 
    int data; 
    struct tree *left; 
    struct tree *right; 
}; 

struct tree* insert(struct tree* node, int data) 
{ 
    if(!node){ 
    node=malloc(sizeof(struct tree)); 
    node->data=data; 
    node->left=node->right=NULL; 
    return node; 
    } 
    else { 
    if(data>node->data){ 
    node->right= insert(node->right,data); 
    return node; 
    } 
    else{ 
    node->left= insert(node->left,data); 
    } 
return node; 
    } 
} 
printtree(struct tree* node) 
{ 
    if(node){ 
     printf("%d",node->data); 
    } 
     printtree(node->left); 
     printtree(node->right); 

} 
main() 
{ 
int i,n; 
struct tree *NODE; 
NODE= insert(NODE,5); 
NODE= insert(NODE,3); 
NODE= insert(NODE,8); 
printtree(NODE); 
} 
+1

Где 'структура node' определяется? – Kninnug

+0

Попробуйте скомпилировать с предупреждениями, чтобы начать видеть, что пошло не так, что вы можете исправить сразу. – Nobilis

+3

Слишком много ошибок. Как отмечает Бретт Хейл, 'struct tree * node' не инициализируется,' struct tree * treenode' нигде не используется, и я также считаю, что в определении структуры оба 'struct node' должны быть' struct tree' –

ответ

2

Локальная переменная: struct tree* node; не инициализирован, поэтому тест if (!node) будет иметь неопределенное поведение. Если вы не назначили ему что-либо или не использовали его для хранения узла malloc'd, выражение в блоке else пытается разыменовать неинициализированный указатель.


Вы также должны привыкнуть к мысли, что дерево можно рассматривать как «рекурсивную» структуру, так что любой узел является деревом, а дерево верхнего уровня является просто узлом. Здесь нет веских оснований для двух отдельных типов.

+0

Я изменил код, но все же он дает ошибку сегментации. «Узлом» вместо «дерева» была ошибка опечатки – user2456752

4

используется if(node), но лучше использовать if(node != NULL)

используется if(!node), но лучше использовать if(node == NULL)

Это делает код более читаемым.

У вас так много ошибок - так ... Я делаю это на своем пути (мой код и т. Д.).

printtree(node->left); printtree(node->right); был вне if(node != NULL){} поэтому пытаются получить NULL->left и NULL->right

Испытано - код работает.

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

struct tree{ 
    int data; 
    struct tree *left; 
    struct tree *right; 
}; 

struct tree* insert(struct tree* node, int data) 
{ 
    if(node == NULL) { 
     node = malloc(sizeof(struct tree)); 
     node->data = data; 
     node->left = node->right = NULL; 
    } else { 
     if(data > node->data){ 
      node->right = insert(node->right, data); 
     } else { 
      node->left = insert(node->left, data); 
     } 
    } 

    return node; 
} 

void printtree(struct tree* node) 
{ 
    if(node != NULL){ 
     printf("%d\n", node->data); 
     printtree(node->left); 
     printtree(node->right); 
    } 
} 

int main() 
{ 
    struct tree *NODE = NULL; 

    NODE = insert(NODE, 5); 
    NODE = insert(NODE, 3); 
    NODE = insert(NODE, 8); 

    printtree(NODE); 

    return 0; 
} 
+0

да, это работает сейчас. Спасибо, кстати. Проблема была в if, но теперь все в порядке! :) И способ, которым я указывал условия if: if (node) «работает также – user2456752

+0

' if (node) 'отлично работает - он может быть менее читабельным для других (для новичков, для учителей, проверяющих ваши знания;)) Вы всегда можете отметить мой ответ, как принято. – furas

+0

+1 Это примерный пример. @ user2456752 - 'if (value)' really * should * будет использоваться только для целых T/F (не 0/0) тестов. Это не очень хорошая практика для указателей «NULL», даже если это законно, и это делает код с большим использованием указателей более трудным для чтения. –

1

Вы по-прежнему совершаете ошибку при передаче NODE по значению. Если вы хотите его изменить, вы должны использовать указатель на этот указатель.

#include<stdio.h> 
#include<stdlib.h> 
typedef struct t 
{ 
    int data; 
    struct t *left; 
    struct t *right; 
}tree; 

tree* insert(tree **node, int data) 
{ 
    if(!(*node)) 
    { 
     *node=malloc(sizeof(tree)); 
     (*node)->data=data; 
     (*node)->left=(*node)->right=NULL; 
     return *node; 
    } 
    else 
    { 
     if(data>(*node)->data) 
     { 
      (*node)->right = insert(&((*node)->right),data); 
      return *node; 
     } 
     else 
     { 
      (*node)->left = insert(&((*node)->left),data); 
      return *node; 
     } 
    } 
} 

void printtree(tree *node) 
{ 
    if(node) 
    { 
     printf("%d",node->data); 
     printtree(node->left); 
     printtree(node->right); 
    } 
} 

void freeMemory(tree *node) 
{ 
    if(node) 
    { 
     freeMemory(node->left); 
     freeMemory(node->right); 
     free(node); 
    } 
} 

int main() 
{ 
    tree *NODE = NULL; 
    NODE= insert(&NODE,5); 
    NODE= insert(&NODE,3); 
    NODE= insert(&NODE,8); 
    printtree(NODE); 
    freeMemory(NODE); 
    return 0; 
} 

Ссылка: http://ideone.com/OpZWiC

+0

Он возвращает указатель узла в качестве результата и назначает NODE - ему не нужно «указатель на указатель». Но он должен сделать это с помощью указателя на указатель, потому что он лучше;) – furas

+0

Комментарий retracted^_ ^, но он действительно должен использовать «указатель на указатель» :) –