Chained List in C Language print inverse list

Asked

Viewed 512 times

0

I need to create a list that gets n we and print these nodes normally and in reverse order, ie 1,2,3 to 3,2,1. I am new in programming area and would be very grateful for the help. I am using Dev C++. I am unable to invert the numbers.

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

struct no       //cria uma estrutura do tipo no
{
    int num;
    struct no *prox;
    struct no *ant;
    } *node;

int main (){
    setlocale (LC_ALL, "Portuguese");
    
    void criar_lista (int n);   //mostra que foi criado uma função criar_lista
    void imprimir_lista ();     //mostra que foi criado uma função imprimir_lista
    void imprimir_lista_inverso ();
    
    int n;                      //declaração de variável n
    
    printf ("Quantidade de nós: ");
    scanf ("%d", &n);
    criar_lista (n);            //chama a função criar_lista
    printf ("\nDados inseridos na lista: \n");
    imprimir_lista ();          //chama a função imprimir_lista
    printf ("\nDados inversos: \n");
    imprimir_lista_inverso ();
    return 0;
}

void criar_lista (int n)        //função criar lista que puxa um valor do tipo inteiro 'n'
{
    struct no *fim_no, *aux;    //declaração da estrutura no com ponteiro para fim_no e aux
    int num, i;
    node = (struct no *) malloc (sizeof (struct no));
    if (node == NULL)
    {
        printf ("Erro no 'if'em criar lista !!");
    }
    else 
    {
        node -> num = num;      //estrutura node na variável num recebe o valor de num
        node -> ant = NULL;     //estrutura node na variável ant recebe o valor de NULL
        node -> prox = NULL;    //estrutura node na variável prox recebe o valor de NULL
    }
    printf ("Digite dados para nó 1: ");
        scanf (" %d", &num);
        node -> num = num;      //estrutura node na variável num recebe o valor de num
        node -> ant = aux;      //estrutura node na variável prox recebe o valor de NULL
        node -> prox = NULL;    //estrutura node na variável prox recebe o valor de NULL
        aux = node;     
    
    for (i = 2; i <= n; ++i)
    {
        fim_no = (struct no *) malloc (sizeof (struct no));
        if (fim_no == NULL)
        {
            printf ("Erro no 'for' em criar lista ");
            break;
        }
        else
        {
            printf ("Digite dados para nó %d: ", i);
            scanf (" %d", &num);
            
            
            fim_no -> num = num;
            fim_no -> prox = NULL;
            aux -> prox = fim_no;
            aux = aux -> prox;
        }
    }
}

void imprimir_lista ()
{
    struct no *aux;
    int ant, prox;
    if (node == NULL)
    {
        printf ("Erro no 'if' de imprimir lista");
    }
    else
    {
        aux = node;
        while (aux != NULL)
        {
            printf ("Dado = %d\n", aux -> num);
            aux = aux -> prox;
        }
    }
}

void imprimir_lista_inverso ()
{
    struct no *aux;
    int ant, prox;
    if (node == NULL)
    {
        printf ("Erro no 'if' de imprimir lista");
    }
    else
    {
        aux = node;
        while (aux != NULL)
        {   
            
            printf ("Dado = %d\n", aux -> num);
            aux = aux -> prox;
        }
    }
}

Thanks for your help.

  • Since it’s a double-chained list, just run it backwards. I think it would be very useful for you to have pointers for both the first and the last node of the list.

2 answers

0


If you use recursiveness your code can be much simpler.

I suggest the following amendments:

1 - in the header:

 void imprimir_lista_inverso (struct no*);

2 - on call:

imprimir_lista_inverso (node);

3 - in the body of the function:

void imprimir_lista_inverso (struct no *aux)
{
    if(aux == NULL)
        return;
    imprimir_lista_inverso(aux->prox);
    printf ("Dado = %d\n", aux -> num);
}       

Here follows a brief explanation of the recursive function: The function is first called with the first element of the list, it is made to check whether this element is NULL (which indicates the end of the recursion). If it is not the last element, first the function is called to the next element and only after returning from that call will the data be printed.

That is, the first impression of data will only occur after the recursion is closed (when the IF criterion is true).

0

I changed the original example a little bit because I had posted wrong and to show the lack it makes Lista not to be a complete structure, but only one knot.

I will leave an example at the end with your code and that creates a list with some elements and shows on the screen. But I think should incorporate the I’m writing next before continuing with your program - @arfneto

struct no       //cria uma estrutura do tipo no
{
    int num;
    struct no *prox;
    struct no *ant;
    } *node;

Write your program around the data. Always. And everything gets simpler. Understand that a linked list NAY is a node and whenever programming a list as if it were a node will take more work without need.

Imagine this structure:

typedef struct
{
    unsigned        size;
    unsigned        limit;
    Node*           inicio;
    Node*           fim;

}   Lista;

By declaring something like Lista will already have a size, a limit, a pointer to the end and another to the beginning. And even if you have 25 lists in the same program each one will have their values preserved WITHIN the structure. This is the concept of encapsulation.

Understand that prototypes should be OUT of main()

And maybe in a header file --- or such . h for example --- separate. The way you wrote it is wrong. It’s nice to use comments in your code, but maybe you could avoid these so obvious:

void criar_lista(int n);   //mostra que foi criado uma função criar_lista
void imprimir_lista();     //mostra que foi criado uma função imprimir_lista
void imprimir_lista_inverso();

And how to invert a list?

You’re the one who’s creating the list.

You can always enter at the beginning, always at the end or in some order.

Let’s imagine that will always insert at the beginning: Then when going through the list to print the values will appear in reverse chronological order, of course: the last inserted will be the first.

When you list the last guy, he will be pointing to NULL. And that will be the pointer to the end of the list. I guess you figured there should be an updated pointer to the bottom of the list, right? And then do exactly the same thing you did to list the elements, but just show the last element, point to his previous one and continue until he doesn’t have a previous one and you will have listed the elements in the reverse order, the insertion order.

These classifications are generically called LIFO and FIFO in literature, of Last In First Out and First In First Out.

list()

Create list should return the address of a List. Avoid returning void: in general it is a waste and often an error. In this case both of you. but what matters is the error: the address of your new list will die there within the function.

Do the simple and create a function too that inserts a value in the list and returns its address for the same reason. Something simple like

    Lista*    insere( int item, node lista);

You don’t need a function to create the list

avoid creating pointer types

This is very problematic and will always fall on your head. In your example, what kind of node? struct no*. What’s the point? How will you know when you read the program a month from now?

Maybe you should use a convention, as I showed in the example, writing the types you define with an uppercase initial, or all uppercase, or an underline on the front, at the end, a prefix, a suffix, anything but.

Understand that only declares variables, so if a node in the list is Node a pointer to it ALWAYS is Node*, a pointer to a pointer to it is Node** and so on. The asterisk speaks for itself in C. In his example node no. you’ll have to remember at all times that Node is a pointer and that’s not good: it’s bad. Well bad.

Don’t read anything from the keyboard

As long as your program is not ready in terms of list do not read anything from the keyboard. It will only delay you and will not be little. It also makes it difficult to repeat tests with the same data. Always read from a file. It’s much easier. You can type files into the IDE itself. Reading from the keyboard is hell and will only slow you down... And before reading from a file use constants in your program and test a little.

An example with your code

Like I said, I think you should write the list structure better. Consider that you don’t actually need a routine to create the list. And that imprimir_lista() should be the first routine running in your program. See this version of main()

int main(void)
{
    setlocale(LC_ALL, "Portuguese");

    Node* teste = NULL;
    imprimir_lista(teste);

    for (int i = 1; i <= 10; i += 1)
        teste = inserir_no_inicio(i, teste);

    Node* ultimo = imprimir_lista(teste);
    Node* primeiro = imprimir_lista_inverso(ultimo);
    // so para fechar o circulo
    ultimo = imprimir_lista(primeiro);

    return 0;
}

You may agree that it is much simpler to read. And test. Since your data is just one int. Call imprimir_lista() at the beginning is an obvious test because has that works with the pointer NULL. Then a for inserts some elements and imprimir_lista() must show the same

As I said at the beginning, this is not a good representation of a list. The simple thing is to have a structure with metadata to control the list, as I showed you. It’s much easier.

Anyway, I changed the routines that print the list to be more cooperative: you can call the routines from anywhere on the list, and imprimir_lista() prints to the end and returns the last one’s address. And imprimir_lista_inverso() prints from position to start, but returns the address of the first.

So you can call one after the other and the circle is complete :D

shows what is expected

imprimir_lista()
imprimir_lista()
Dado = 10
Dado = 9
Dado = 8
Dado = 7
Dado = 6
Dado = 5
Dado = 4
Dado = 3
Dado = 2
Dado = 1
imprimir_lista_inverso()
Dado = 1
Dado = 2
Dado = 3
Dado = 4
Dado = 5
Dado = 6
Dado = 7
Dado = 8
Dado = 9
Dado = 10
imprimir_lista()
Dado = 10
Dado = 9
Dado = 8
Dado = 7
Dado = 6
Dado = 5
Dado = 4
Dado = 3
Dado = 2
Dado = 1

The program, almost the same

Run and compare the program. I suggest to put the pointer to the end and make all the changes as listed. If you have more questions write and I complete the example with something...

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

struct no
{
    int num;
    struct no* prox;
    struct no* ant;

} *node;

typedef struct no Node;

typedef struct
{
    unsigned        size;
    unsigned        limit;
    Node* inicio;
    Node* fim;

}   Lista;

Node*       criar_lista(int n);   //mostra que foi criado uma função criar_lista
Node*       imprimir_lista(Node*);
Node*       imprimir_lista_inverso(Node*);
Node*       inserir_no_inicio(int, Node*);

int main(void)
{
    setlocale(LC_ALL, "Portuguese");

    Node* teste = NULL;
    imprimir_lista(teste);

    for (int i = 1; i <= 10; i += 1)
        teste = inserir_no_inicio(i, teste);

    Node* ultimo = imprimir_lista(teste);
    Node* primeiro = imprimir_lista_inverso(ultimo);
    // so para fechar o circulo
    ultimo = imprimir_lista(primeiro);

    return 0;
}

Node* criar_lista(int n)        //função criar lista que puxa um valor do tipo inteiro 'n'
{
    /*
    Node* novo = (Node*) malloc ( sizeof(Node) );
    if (node == NULL) return NULL;
    node->num = num;
        node->ant = NULL;     //estrutura node na variável ant recebe o valor de NULL
        node->prox = NULL;    //estrutura node na variável prox recebe o valor de NULL
    }
    printf("Digite dados para nó 1: ");
    scanf(" %d", &num);
    node->num = num;      //estrutura node na variável num recebe o valor de num
    node->ant = aux;      //estrutura node na variável prox recebe o valor de NULL
    node->prox = NULL;    //estrutura node na variável prox recebe o valor de NULL
    aux = node;

    for (i = 2; i <= n; ++i)
    {
        fim_no = (struct no*)malloc(sizeof(struct no));
        if (fim_no == NULL)
        {
            printf("Erro no 'for' em criar lista ");
            break;
        }
        else
        {
            printf("Digite dados para nó %d: ", i);
            scanf(" %d", &num);


            fim_no->num = num;
            fim_no->prox = NULL;
            aux->prox = fim_no;
            aux = aux->prox;
        }
    }
    */
    return NULL;
};


Node*       imprimir_lista(Node* L)
{
    // imprime a lista a partir de L 
    // e retorna o endereco do ultimo cara
    printf("imprimir_lista()\n");
    if (L == NULL) return NULL;
    Node* p = L;
    Node* ultimo = NULL;
    while (p != NULL)
    {
        printf("Dado = %d\n", p->num);
        ultimo = p;
        p = p->prox;
    };
    return ultimo; // retorna o total de itens
};


Node*       imprimir_lista_inverso(Node* L)
{
    // imprime a lista a partir de L, para tras, 
    // e retorna o endereco do primeiro cara
    printf("imprimir_lista_inverso()\n");
    if (L == NULL) return NULL;
    Node* p = L;
    Node* primeiro = NULL;
    while (p != NULL)
    {
        printf("Dado = %d\n", p->num);
        primeiro = p;
        p = p->ant;
    };
    return primeiro; // retorna o total de itens
}


Node* inserir_no_inicio(int n, Node* L)
{
    // a lista existe, mas pode estar vazia
    // vai inserir sempre no inicio nesse exemplo
    Node* novo = (Node*)malloc(sizeof(Node));
    novo->num = n;
    novo->ant = NULL; // vai ficar no inicio
    novo->prox = L; // vai apontar para o que estava na frente
    if (L != NULL) L->ant = novo;
    return novo;
};

// fim
  • I tried to run this code, but it gives error in the print_list (test), you can tell me why?

  • @Renanpereira I’m sorry: I had written using the structure Lista as I showed you, but then I thought I should post an example using its own structure and forgot to pass the parameter to imprime_lista() That’s why it didn’t work. I typed it right into the OS :( my bad. Now I took the opportunity to change the printing routines for you to see how it is necessary not to have the pointers updated INSIDE the structure. Sorry.

Browser other questions tagged

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