Copy list simply chained in C

Asked

Viewed 2,436 times

0

Hey, guys, I need help copying a list just chained up backwards. For example, if the original list is 1->2->3->null, I need it to be 3->2->1->null.

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

typedef int bool;
enum { false, true };

// elemento da lista
typedef struct estr {
    char letra;
    struct estr *prox;
} NO;

typedef struct {
    NO *inicio;
} LISTA;

void inicializarLista(LISTA *l) {
    l->inicio = NULL;
}

void criarLista(LISTA *l, char plvr[]) {
    NO *ult = NULL;
    for (int i = 0; i < strlen(plvr); i++) {
        NO *novo = (NO *) malloc(sizeof(NO));
        novo->letra = plvr[i];
        novo->prox = NULL;
        if (ult) {
            ult->prox = novo;
        } else {
            l->inicio = novo;
        }
        ult = novo;
    }
}

void imprimirLista(LISTA l) {
    NO *p = l.inicio;
    while(p) {
        printf("%c", p->letra);
        p = p->prox;
    }
}

LISTA* clonarLista(LISTA* l){
  NO novo = NULL;
  LISTA* resp = novo; //inicializar lista resp
  while(l){
    novo = (NO *) malloc(sizeof(NO));
    novo->letra = l->letra;
    novo->prox = NULL;
    l = l->prox;
  }
  return resp;
}

void inverter(LISTA* resp){
  NO* ant = NULL;
  NO* atual = //inicio da lista resp
  NO* seg; //seguinte
  while (atual){
    seg = atual->prox;  
    atual->prox = ant;   
    ant = atual;
    atual = atual->prox;
    }
    //inicio da lista resp = ant;
}

int main() {
    LISTA l;
    LISTA resp;
    inicializarLista(&l);
    inicializarLista(resp);
    char palavra[] = "caio";
    criarLista(&l, palavra);
    inverter(&resp)
    imprimirLista(resp);

    return 0;
}

1 answer

2


The flip function has a variable with the open value:

NO* atual = //inicio da lista resp

Which generates a syntax error because the value and the ;. Just as logic does not do what is intended. Instead you can rebuild the list by adding nodes to the head which will do the inversion:

void inverter(LISTA* resp){

    NO* atual = resp->inicio;

    //redefinir a lista para começar vazia, sendo que o ponteiro atual ainda 
    //aponta para os seus elementos
    resp->inicio = NULL; 

    while (atual){ //enquanto tiver nós
        NO* corrente = atual; //guardar o nó corrente
        atual = atual->prox; //avançar o nó atual


        corrente->prox = resp->inicio; //fazer o prox do corrente ser o 1 da lista invertida
        resp->inicio = corrente; //o inicio passa a ser este ultimo nó
    }
}

The list printing function should receive a pointer, equal to the one the other functions receive, so that:

void imprimirLista(LISTA *l) { //agora com *l
    NO *p = l->inicio; //agora com ->
    while(p) {
        printf("%c", p->letra);
        p = p->prox;
    }
}

What does the main become different. And the main that had, reversed a list that had no value assigned, the list resp, just as he lacked one &. Then it should stay that way:

int main() {
    LISTA l;
    LISTA resp;
    inicializarLista(&l);
    inicializarLista(&resp); //agora com &
    char palavra[] = "caio";
    criarLista(&l, palavra);
    inverter(&l); //inverter o l que é o que tem a palavra
    imprimirLista(&l); //imprimir o que foi invertido

    return 0;
}

Edit:

To invert a clone from the original list you first need to hit the cloning function that has some things wrong:

  • NO novo = NULL; is an invalid boot unless it is a pointer
  • novo->letra = l->letra; I’m kind of LISTA then just have the field inicio and not the field letra and the same happens in while(l) not useful for navigation
  • The construction of prox of the new nodes, so that the list gets all the elements connected

Making things right we’re left with:

LISTA* clonarLista(LISTA* l){
  LISTA* resp = malloc(sizeof(LISTA)); 

  NO *corrente = l->inicio;
  NO *anterior = NULL; //utilizar um nó anterior para ligar os vários elementos

  while(corrente){ //agora com corrente em vez de l
    NO *novo = (NO *) malloc(sizeof(NO));
    novo->letra = corrente->letra;
    novo->prox = NULL;

    if (anterior == NULL){ //se é o primeiro fica no inicio da nova lista
        resp->inicio = novo;
    }
    else { //se não é o primeiro liga o anterior a este pelo prox
        anterior->prox = corrente;
    }

    anterior = novo;
    corrente = corrente->prox;
  }

  return resp;
}

So that the main invert a copy instead of the original we can change to:

int main() {
    LISTA l;
    inicializarLista(&l);
    char palavra[] = "caio";
    criarLista(&l, palavra);

    LISTA* resp = clonarLista(&l); //obter o clonado
    inverter(resp); //inverter o clonado
    imprimirLista(resp); //imprimir o clonado -> oaic

    return 0;
}
  • Isac, the problem lies in the fact that in your solution a new list has not actually been created. I mean, through Malloc.

  • @Caio_ignatz In his original logic he also did not have malloc, and so I deduced that I wanted to invert the list that is received as a parameter in the function inverter, and not create a new inverted. But I don’t know if I’m getting what you’re saying correctly, try to be a little more specific.

  • first, I need to copy the received list. Second, I need to create a new list from the inversion of the received list. I wasn’t clear on that point.

  • @Caio_ignatz I already edited in this sense, I calculated that this is what I wanted due to the cloning function.

  • It worked, Isac. Thank you very much! You helped a lot. Now I’m going to study your code

  • @Caio_ignatz No problem, good study.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.