How to create a dynamic chained list within another dynamic list in C?

Asked

Viewed 4,158 times

4

I’m having a really hard time creating a dynamically chained list inside another one using data structure. I can create a dynamic list, but I can’t create another one inside it.

To illustrate what I mean:

I have a list of Bands; each band is a list of albuns; and each album is a list of music. And in the program the user can include songs and remove them at any time, include albums and remove them at any time, and include bands and remove them at any time.

My code is like this, but it doesn’t work, There must be a lot of nonsense:

File . C

#include "biblioteca.h"

ElemM *lm;
ElemA *la;
ElemB *lb;
//---------------------------MAIN--------------------------------->

int main()
{
  lb = cria_lista_banda();
  la =  cria_lista_album();
  lm = cria_lista_musica();


  system("PAUSE");  
  return 0;
} 
//----------------------------------------------------------------->

ElemB *cria_lista_banda(){
        ElemB *lb;
        lb =  malloc(sizeof(ElemB));
        lb->prox_banda = NULL;
        return lb;


}

ElemA *cria_lista_album(){
        ElemA *la;
        la =  malloc(sizeof(ElemA));
        la->prox_album= NULL;
        return la;


}

ElemM *cria_lista_musica(){
        ElemM *lm;
        lm =  malloc(sizeof(ElemM));
        lm->prox_musica= NULL;
        return lm;


}

int incluir_musica(ElemM *lm, ElemA *la, ElemB *lb, int id_m, int tempo, char *nome_m, int id_a, int id_b){
        int valor1, valor2, valor3, i;

        valor1 = busca_banda(id_b, lb);
        valor2 = busca_album(id_b, id_a, lb, la);
        valor3 = busca_musica(id_b, id_a, id_m, lb, la, lm);
        if(valor3 == -1) return -1;

        ElemB *q;
        q = lb->prox_banda;
        for(i = 0; i <= valor1; i++){
              q = q->prox_banda;
        }
        ElemA *p;
        p = q->albuns_da_banda->prox_album;
        for(i = 0; i <= valor2; i++){
             p = p->prox_album;         
        }

        ElemM *novo, *novocpy;
        p->musicas_do_album->novo = malloc( sizeof(ElemM));
        novocpy = p->musica_do_album->novo;
        if(novo == NULL) return 0;
        novocpy->id_musica = id_m;
        novocpy->tempo_da_musica = tempo;
        strcpy(novocpy->nome_musica, nome_m);
        novocpy->prox_musica = lc->prox_musica;
        lm->prox_musica = novocpy;
        return 1;
}

int busca_banda(int id, ElemB *lb){
        int cont = 0;
        ElemB *p;
        p = lb->prox_banda;
        while(p != NULL && p->id_banda != id){
                p = p->prox_banda;
                cont++;
        }
        if(p == NULL) return -1;
        return cont;
}

int buscar_album(int id_b, int id_a, ElemB *lb, ElemR *la){
        int valor_busca = busca_banda(id_b, lb); 
        int i;
        int cont = 0;

        if(valor_busca == -1) return -1;
        ElemB *q;
        q = lb->prox_banda;
        for(i = 0; i <= valor_busca; i++){
              q = q->prox_banda;
        }
        ElemA *p;
        p = q->albuns_da_banda->prox_album;
        while(p != NULL && p->id_album != id_a){
             p = p->prox_album;
             cont++;         
        }      

        if(p != NULL) return -1;
        return cont;   

}


int buscar_musica(int id_b, int id_a, int id_m, ElemB *lb, ElemA *la, ElemM *lm){
        int valor_busca1 = busca_banda(id_b, lb);
        int valor_busca2 = busca_album(id_b, id_a, lb, la); 
        int i;
        int cont = 0;

        if(valor_busca1 == -1) return -1;
        if(valor_busca2 == -1) return -1;
        ElemB *q;
        q = lb->prox_banda;
        for(i = 0; i <= valor_busca1; i++){
              q = q->prox_banda;
        }
        ElemA *p;
        p = q->albuns_da_banda->prox_album;
        for(i = 0; i <= valor_busca2; i++){
             p = p->prox_album;         
        }
        ElemM *k;
        k = p->musica_do_album->prox_musica;
        while(k != NULL && k->id_musica != id_m){
             k = k->prox_musica;
             cont++;         
        }       

        if(k != NULL) return -1;
        return cont;   

}

File . h

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

struct musica{
       int id_musica;
       int tempo_musica;
       char nome_musica[30];
       struct casa *prox_musica;
       };      

typedef struct casa ElemM;

struct album{
       int id_album;
       char nome_album[30];
       struct casa *musica_do_album;
       struct rua *prox_album;
       };

typedef struct album ElemA;

struct banda{
       int id_banda;
       char nome_banda[30];
       struct album *albuns_da_banda;
       struct banda *prox_banda;
       };       

typedef struct banda ElemB;


ElemB *cria_lista_banda();
ElemR *cria_lista_album();
ElemC *cria_lista_musica();
int incluir_musica(ElemM *lm, ElemA *la, ElemB *lb, int id_m, int tempo, char *nome_m, int id_a, int id_b)
int busca_banda(int id, ElemB *lb);
int buscar_album(int id_b, int id_a, ElemB *lb, ElemR *la);
int buscar_musica(int id_b, int id_a, int id_m, ElemB *lb, ElemA *la, ElemM *lm);

@pedro-Witzel and @hugomg , the above files have been edited to as they are now. They’re not working and the sources I’m using to try to solve this problem don’t talk about list within list, and I can’t find anything related to this, just how to make a "normal" chained list, could help me once again?

Note: The -1 value indicates that something happened and made the program not reach the goal.

2 answers

1

The variables prox_* has the wrong name, which can lead to confusion. For example, prox_musica is typified with album.

If the intention is to create chained lists, the ideal is that the variable has a pointer to another of the same type.

So the struct musica would be:

struct musica{
       int id_musica;
       int tempo_da_musica;
       char nome_musica[30];
       struct musica *prox_musica;
       };   

And the album struct would be

struct album{
         int id_album;
         char nome_album[50];
         struct musica *primeira_musica;
         struct album *prox_album;
         };    

Same for the other structs. Notice I changed the name of dados_musica for primeira_musica and its kind for a pointer.

When you’re making the loop to scroll through the songs of an album, take the pointer to the first song to start, and with each iteration, take the next song until it’s null

for (struct musica *pMusica = album.primeira_musica; 
     pMusica != NULL;
     pMusica = pMusica->prox_musica)
{
   ///Faça o que quiser
}

To add a new entry in a chained list it is necessary to first create the new object and update the previous one with its reference:

struct musica nova_musica;
musica_anterior.prox_musica = &nova_musica;

If you have allocated the objects in the stack you have to go through all the lists recursively (from the producer, in your case) to free up the created space.

struct musica *pMusica = album.primeira_musica; 
while (pMusica != NULL)
{
    struct musica *pProx_musica = pMusica->prox_musica;
    free(pMusica);
    pMusica = pProx_musica;
}

Source: IME-USP

  • Could you give a few tips on how to create list deletion function at the end of the program, or even the inclusion of elements? I’m trying to create them here, but they generate many mistakes that I end up taking a long time to fix. Thank you very much

  • @Joãom.Silva, I updated the answer. But since I do not know exactly what you want, I gave half-open answers. If you still have doubts, take a look at the source link, the material is interesting.

  • I’m using the material that is on the source link to try to make this program, but I’m still not able to understand how to insert/search a song in the right album and the right band, even with your previous help. I’m having a really hard time getting this done. Thank you so much for your help.

  • I edited the code for how it was now and in the text, could you take a look? Grateful.

0


Assuming that each song can only be on a single album and that each album can only belong to a single band, the notmal would be to make each album node contain a pointer to the first song on its list and that make each band node contain a pointer to the first album on its list.

The pointer to the first element of a chained list is the way to store the list.

struct banda {
    int id_banda;
    char nome_banda[50];
    struct album *albums_da_banda;
    struct banda *prox_banda;
};

struct album {
    int id_album;
    char nome_album[50];
    struct musica *musicas_do_album;
    struct album *prox_album;
};

struct musica {
    int id_musica;
    char nome_musica[50];
    struct musica *prox_musica;
};

As for "has nonsense", I’m not a fan of typedefs like "Elemento_album" and "Listaalbuns". Some people like it but I think it gets confusing when a typedef hides the fact that something is a pointer.

Usually I just do a typedef so I don’t have to type "struct" all the time.

typedef struct album {
     ...
} album;

But the rules for this type of typedef are a little confusing when you have recursive structures. In your case I think it might be easier to leave without typedef for now.

Another parallel suggestion is to use uppercase letters in the name of your types. So you can see right away what is a type qe what is a variable in your program.

struct Album { ... };
  • I’m sorry, but I didn’t quite understand what the .h. file would look like. h, now they will stay in this new music struct you wrote? Thank you

  • Could you give me a tip on how to continue my program? How to create functions to include and delete from the list? Thank you very much.

  • The type statements I suggested go to ". h". Already the functions to insert new elements I suggest you try to do it yourself. If I do everything it’s not funny :)

  • I will try :) - But wouldn’t you have something to read or some video that addresses this topic? Thank you

  • Chained list is the kind of thing you’ll find in almost any introductory material. I think better what you’re already using. If you want to go deeper, find a good book of data structures (like Sedgewick’s)

  • I edited the code for how it was now and in the text, could you take a look? Thank you. -

  • If it’s working, I don’t need to take a look :) If it’s not, you’d better ask a separate question instead of continuing to edit this one. So more people can help. And as always, try to ask objective questions and make clear which error is occurring.

Show 2 more comments

Browser other questions tagged

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