Segmetation fault error - Problem in main code for insertion of binary tree nodes

0

I'm doing a program that reads records and saves these records in a linked list and in a binary tree.

However, I am not able to save the nodes in the binary tree, appearing a segment fault error.

I'd like to know why this error appears and how to fix it.

Here is my main.c file:

int main(){

registro p1_main;
lista   p2_main;
nodo p3_main;
int escolha1 = 99, escolha2;


criarLista(&p2_main);
cria_arvore(&p3_main);
do {
    printf("Qual opção a seguir você deseja realizar?\n\n1-Adicionar Contato\n2-Apresentar nomes registrados\n\n");
    scanf("%d", &escolha1);

switch(escolha1){
    case 1:
        criar_registro(&p1_main);
        insere_ini(&p2_main, &p1_main);
        CriarNodo(&p1_main);
        insere_Arvore(&p3_main, &p1_main);
    case 2:
        imprime_nomes(&p2_main);
    }
}
while ( escolha1 != 0);


return 0;

}

Here is the structure.h of the codes:

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

typedef struct registro_st{         // sequência de objetos do mesmo tipo
    char login[50];
    char nome[50];
    float valor;
} registro;

typedef struct nodo_st{
    registro *dado;
    struct nodo_st *dir;
    struct nodo_st *esq;
} nodo;

typedef struct Lista_st{
    nodo *cabeca;
    nodo *cauda;
    int tamanho;
} lista;

nodo* CriarNodo(registro * p){
        nodo* n;
        n = (nodo*)malloc(sizeof(nodo));
        n->dado = p;
        n->dir = NULL;
        n->esq = NULL;
        return n;
}

void criarLista(lista *l){
    l->cauda = NULL;
    l->cabeca = NULL;
    l->tamanho = 0;
}



void insere_ini(lista *l, registro* dado){
    nodo* novo = (nodo*)malloc(sizeof(nodo));
        if(novo == NULL){
            return 0; //falta de espaço
        };


        novo->dado = dado;
        novo->dir = l->cauda; //antigo primeiro aponta para o próximo
        l->cauda = novo;        // novo nodo recebe ponteiro para começo
        l->tamanho = l->tamanho + 1;
        printf("\n\nEsse foi o registro de num: %d.\n", l->tamanho);
        printf("\nnodo implementado!!\n");
        return novo;
}

nodo* raiz;

//FUNÇÕES PARA UTILIZAR NO MAIN

void imprime_nomes(lista *l){            // função que imprime os valores
        nodo* p = l->cauda;
            while(p)
            {                                           // Usando while, não é necessário estabelecer um loop para percorrer toda lista.
            printf("Login eh: %s\n", p->dado->login);
            printf("Nome eh: %s\n", p->dado->nome);
            p = p->dir;
            }
}

void criar_registro(registro *p){                   //função para adicionar os contatos
    printf("Qual login para registro:\n");
    scanf("%s", &p->login);
    printf("Qual o nome do contato:\n");
    scanf("%s", &p->nome);
    printf("Qual valor para registrar:\n");
    scanf("%f", &p->valor);
}

nodo* raiz; //porque um ponteiro para um ponteiro?

nodo* cria_arvore(){                            //função para criar árvore
    nodo* raiz = (nodo*)malloc(sizeof(nodo));
    if(raiz != NULL)
        {
        return raiz;
        }
    }


void insere_Arvore(nodo **raiz, struct registro_st *registro)
{
    //o compilador faz sempre cast de void* para o tipo indicado, não sendo assim necessário
    nodo* novo = malloc(sizeof(nodo)); /*agora sem cast pois é desnecessário*/
    if(novo == NULL)
    {
        return; /* é void logo não pode ter tipo de retorno*/
    }

    novo->dado = registro; //o dado é o registro todo em si
    novo->dir = NULL;
    novo->esq= NULL;

    if(*raiz == NULL) //ver se o valor do ponteiro é null, logo arvore vazia
    {
        *raiz = novo;
        return;
    }

    nodo* atual = *raiz;
    nodo* ant = NULL;


    while(atual != NULL) //ciclo agora só para navegar até ao sitio correto
    {
        ant = atual;

        //o valor a ser inserido vem no próprio registro, com registro->valor
        if (registro->valor == atual->dado->valor)
        {
            free(novo);
            return; /* é void logo não pode ter tipo de retorno*/
        }

        if(registro->valor > atual->dado->valor)
        {
            atual = atual->dir;
        }
        else
        {
            atual = atual->esq;
        }
    }

    //após navegar é feita a inserção pelo no anterior.
    if (registro->valor > ant->dado->valor){ //se maior que o anterior fica a direita
        ant->dir = novo;
    }
    else { //senão fica a esquerda
        ant->esq = novo;
    }
}
    
asked by anonymous 24.07.2017 / 01:15

1 answer

2

Your use of the tree is not correct according to your last question that I answered. In your main you have:

int main(){
   ...
   nodo p3_main;

When the tree must be a pointer, to work with the created functions, as well as having the start value of NULL as I had exemplified. This should then be:

int main(){
   ...
   nodo *p3_main = NULL; //agora com valor inicial de NULL

Note that it is very important that you have this start value otherwise when you navigate the cycle it will never stop:

...
while(atual != NULL)
...

Just as you'll never know if the list is empty:

...
if(*raiz == NULL) //ver se o valor do ponteiro é null, logo arvore vazia
{
   ...

Also, the cria_arvore function is not required because the tree insertion function called insere_Arvore already contemplates that the tree is empty and then creates the first node individually, here:

if(*raiz == NULL) //ver se o valor do ponteiro é null, logo arvore vazia
{
   *raiz = novo;
   return;
}

And the call to cria_arvore should be removed:

int main(){
   ...
   nodo *p3_main = NULL; //agora com valor inicial de NULL
   ...
   /*cria_arvore(&p3_main); //agora sem o cria_arvore pois não é necessário*/

And these little changes will already make the program work

    
24.07.2017 / 14:19