How to create a linked dynamic list inside another dynamic list in C?

3

I'm having a hard time getting a dynamically linked list inside another using data structure. I can create a dynamic list, but I can not create another one within it.

To illustrate what I mean:

I have a list of Bands ; each band is a list of albums ; and each album is a list of music . And in the program the user can include songs and remove them whenever they want, include albums and remove them whenever they want, and include bands and remove them whenever they want.

My code is like this, but it does not work, must have a lot of nonsense :

.C file

#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;   

}

.h file

#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 for how they are now. They are not working and the fonts I am using to try to solve this problem do not talk about list inside another, and I can not find anything related to it, just how to make a "normal" linked list, could they help me one more time? / p>

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

    
asked by anonymous 03.05.2015 / 01:12

2 answers

0

Assuming that each song can only be in 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 of its list and that make each bandwidth contain a pointer to the first album on your list.

The pointer to the first element of a linked 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 the "meaningless thing", I'm not much of a fan of typedefs like "Album_element" and "Albumlist". There are people who like it but I think it gets confusing when a typedef hides the fact that something is a pointer.

Normally I only do one typedef so I do not have to be typing "struct" all the time.

typedef struct album {
     ...
} album;

But the rules for this type of typedef are a bit 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 capitalize the names of your types. So let's see right away what a type is and what a variable is in your program.

struct Album { ... };
    
03.05.2015 / 02:03
1

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

If the intent is to create linked lists, the ideal is for the variable to have a pointer to another of the same type.

Then, the struct musica would be:

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

And the struct of the album 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 that I changed the name of dados_musica to primeira_musica and its type to a pointer.

When looping through the songs in an album, grab the first song pointer to start, and at each iteration, grab the next one until it is 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 linked list you must first create the new object and update the previous one with your reference:

struct musica nova_musica;
musica_anterior.prox_musica = &nova_musica;

If you have allocated the objects in the stack you will have to go through all the lists recursively (from the producer, in your case) to release 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

    
03.05.2015 / 02:03