Jump to content
msc126

Lista Ligada Genérica

Recommended Posts

msc126

Boa tarde, sou novo por aqui...

Será que alguém me pode ajudar na funcão de inserir numa lista genérica.

A estrutura pelo que sei é a seguinte:

typedef struct lista {
  void *data;
  struct lista *next;
} Lista;

Tenho dúvidas quanto a utilizar a data seja ela de qualquer tipo.

Obrigado desde já!

Share this post


Link to post
Share on other sites
Diutsu

Utilizar como? Basicamente precisas de ter uma função que recebe void* data, para inserires um novo elemento e outra que devolve void* para remover.

A menos que vás precisar de comparar diferentes elementos "data" na lista.


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
msc126

Não preciso de usar diferentes tipos de "data" na lista, preciso é de reutilizar a estrutura para aplicar a várias situações.

o cabeçalho da inserir está assim:

List *add(List *l, void *info);

Faço uma função de inserir em lista ligada "normal" por assim dizer. O problema está em fazer o cast para vários tipos de dados...

Share this post


Link to post
Share on other sites
Diutsu

Não preciso de usar diferentes tipos de "data" na lista, preciso é de reutilizar a estrutura para aplicar a várias situações.

o cabeçalho da inserir está assim:

List *add(List *l, void *info);

Faço uma função de inserir em lista ligada "normal" por assim dizer. O problema está em fazer o cast para vários tipos de dados...

O cast fica do lado da "aplicação" que usa a lista ligada. Para a lista ligada só lhe interessa que recebe qualquer coisa (void *).


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
msc126

Depois de tentar, continuo a não conseguir fazer o que quero.

O que pretendia era dada uma estrutura de lista ligada genérica ter (entre outras) a funcão genérica como "insertList(List l, void *data)" que serviria inserir diferentes tipos de dados em diferentes listas, ou seja, numa lista com a função insertList, inseriria inteiros, noutra lista strings...

Espero ter-me feito perceber...

Share this post


Link to post
Share on other sites
Diutsu

Sim percebi. Podes por o código que tens da lista aqui?


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
msc126

typedef struct list {
  void *data;
  struct list *next;
} *List, NList;

List insertList(List l, void *data) {
  if (!l) {
    List aux = (List)malloc(sizeof(NList));
    aux->data = data;
    aux->next = NULL;
    return aux;
  }
  else {
    l->next = insertList(l->next, data);
    return l;
  }
}

Tenho isto, não sei se serve, e se servir como utilizar para usar qualquer tipo de dados :/

Share this post


Link to post
Share on other sites
Diutsu

Não seria essa a maneira como eu o fazia, mas assim também dá (iterativo vs recursivo).

No if(!l) a condição que devias estar a verificar devia ser if(l == NULL), por uma questão de legibilidade do código.

Dito isto, o teu código está bem. Para adicionares um novo elemento à lista o que tens de fazer é algo tipo isto:

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

typedef struct list{
 void *data;
 struct list *next;
} *List, NList;

List insertList(List l, void* data){
if (l==NULL) {
	List aux = (List)malloc(sizeof(NList));
	aux->data = data;
	aux->next = NULL;
	return aux;
}
else{
	l->next = insertList(l->next, data);
	return l;
}
}

int main(){

int a=3;
int b=6;
int c=7;

int *pta =&a;
int *ptb =&b;
int *ptc =&c;

//isto não devia ser assim, era uma funcao para iniciar a lista
List lst = NULL;

lst = insertList(lst,(void*) pta);
insertList(lst,(void*) ptb);
insertList(lst,(void*) ptc);

//outra função devolve void* para ler um elemento da lista
printf("%d %d %d", *(int*)lst->data, *(int*)lst->next->data, *(int*)lst->next->next->data);



return 0;
}

como podes verificar sempre que inicias uma nova lista tens de colocar a variavel a NULL e depois de inserires o 1º elemento tens de actualizar essa variável, isto é facilmente resolvido usando uma estrutura intermédia.

eu usei ints, mas usares floats, strings, ou structs também funciona.

[this shouldn't be here]Até usando vários tipos misturados, desde que não saibas a que tipo corresponde o elemento que estás a ler.


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
stoned

Utilizar como? Basicamente precisas de ter uma função que recebe void* data, para inserires um novo elemento e outra que devolve void* para remover.

A menos que vás precisar de comparar diferentes elementos "data" na lista.

Podes desenvolver a parte do comparar diferentes elementos "data" na lista?

Por exemplo, imagina que eu quero adaptar a estrutura genérica

typedef struct list{
         void *data;
         struct list *next;
} *List, NList;

List insertList(List l, void* data){
        if (l==NULL) {
                List aux = (List)malloc(sizeof(NList));
                aux->data = data;
                aux->next = NULL;
                return aux;
        }
        else{
                l->next = insertList(l->next, data);
                return l;
        }
}

a uma lista ligada de alunos, por exemplo.

typedef struct alunos {
          int numero;
          char* nome;
          int notas[10];
          struct alunos *next;
} *Lalunos, NLalunos;

Se quisesse fazer inserção ordenada na lista, por número de aluno, teria de criar uma função de comparação? É isso que queres dizer?

E já agora, num caso prático, como é que eu utilizaria a lista genérica em si para modelar a minha lista ligada de alunos? Por exemplo, para inserir um aluno teria de utilizar a função de inserção genérica - List insertList(List l, void* data), correcto?

Mas de que forma lhe passo os argumentos que quero armazenar? Suponho que seja com casting, mas já procurei bastante sobre isto mas nunca encontro exemplos concretos e nem sempre é fácil perceber... :/

Agradeço desde já qualquer resposta...

Share this post


Link to post
Share on other sites
Diutsu

exacto tinhas de criar uma função de comparação e depois chamares a função dentro da lista, pelo que terias de passar a função como parametro para a lista, coisa que o C não suporta "nativamente".

A ideia é separes por completo a implementação da lista, dos elementos guardados dentro da lista, tendo para tal de usares void*, e fazendo os casts para void* quando inseres um elemento, e para (elemento*) quando queres ler um elemento da lista.

Dá uma olhadela a isto, (a estrutura é um red black tree, é mais complexa que uma lista ligada, portanto não ligues muito ao conteúdo das funções (rotates e fixups não te interessam)) para perceberes como enviar e receber elementos http://wiki.portugal-a-programar.pt/dev_geral:c:red_black_tree


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
Surtr

  
aux->data = data;

Cuidado com isto, estás a passar o endereço de data e não o valor apontado por data. Esta partilha de endereços acaba por dar estouro, mais tarde ou mais cedo, pois a alocação de memória passa a ser responsabilidade do utilizador. O melhor seria passares um campo size_t datasize à tua estrutura, alocares memória para isso e depois usares memcpy.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.