Buenos Dias.
Queria consultar como podia hacer para eliminar todos los elementos repetidos de una lista.
En este caso lo que hice fue crear una lista que contenga a una estructura y lo que tengo que hacer es que elimine todos los nodos cuyo apellido sea "Lopez".
Lo intento hacer y elimina algunos elementos pero no todos, el problema esta en la función eliminar pero no se como modificarla para que elimine todos y no algunos.
#include <stdio.h>
#include <stdlib.h>
struct s_datos
{
char*nombre;
char*apellido;
int dni;
};
typedef struct s_datos t_dato;
struct s_nodo
{
t_dato dato;
struct s_nodo*sig;
};
typedef struct s_nodo*t_nodo;
void agregar(t_nodo*,t_dato);
void imprimir(t_nodo);
void eliminar(t_nodo*,char*);
t_dato cargarstruct();
char*cargatexto();
int main()
{
t_nodo lista=NULL;
agregar(&lista,cargarstruct());
agregar(&lista,cargarstruct());
agregar(&lista,cargarstruct());
agregar(&lista,cargarstruct());
agregar(&lista,cargarstruct());
imprimir(lista);
eliminar(&lista,"Lopez");
printf("\nLista con eliminados\n");
imprimir(lista);
return 0;
}
t_dato cargarstruct()
{
t_dato datito;
///CARGAR ESTRUCTURA
printf("\nIngrese Nombre:\n");
datito.nombre=cargatexto();
printf("\nIngrese Apellido:\n");
datito.apellido=cargatexto();
printf("\nIngrese DNI:\n");
scanf("%d",&datito.dni);
return datito;
}
void agregar(t_nodo*nodo,t_dato datito)
{
if(*nodo==NULL)
{
*nodo=(t_nodo)malloc (sizeof(struct s_nodo));
(*nodo)->dato=datito;
(*nodo)->sig=NULL;
}
else
{
agregar(&(*nodo)->sig,datito);
}
}
void imprimir(t_nodo lista)
{
if(lista!=NULL)
{
printf("\nNombre: %s - Apellido: %s - DNI: %d",lista->dato.nombre,lista->dato.apellido,lista->dato.dni);
imprimir(lista->sig);
}
}
void eliminar(t_nodo*nodo,char*texto)
{
t_nodo aux=NULL;
if(*nodo==NULL)
{
return;
}
else if((strcmp((*nodo)->dato.apellido,texto))==0)
{
aux=(*nodo);
*nodo=(*nodo)->sig;
free(aux);
eliminar(&(*nodo)->sig,texto);
}
else
{
eliminar(&(*nodo)->sig,texto);
}
}
char*cargatexto()
{
char letra;
int i=0;
char*txt=NULL;
txt=malloc(sizeof(char));
letra=getche();
while(letra!='\r')
{
*(txt+i)=letra;
i++;
txt=realloc(txt,(i+1)*sizeof(char));
letra=getche();
}
*(txt+i)='\0';
return txt;
}
Muchas gracias.
Hola, creo que deberías hacer la comparación fuera de la función así solo se encarga de borrar el nodo. También veo que en la linea 81 y 85 llamas la función de manera recursiva, no sé si tu profesor te lo pidió explicitamente de esta forma.
No se de C pero puede que la nomenclatura en punteros sea la misma que en C++ asíi que por si acaso te dejo aquí unos consejos (si funcionan en C xD).
Primero: Yo usaría más los espacios, cuesta de leer el código:
char *nombre;
//o
char* nombre;
Se leen mejor que:
char*nombre;
y eso se aplicaría para las funciones o cualquier declaración con punteros.
Segundo: para hacer typedef de struct(al menos en C++) no hace falta poner struct
char *nombre
//o
char* nombre
Tercero: Cuando pasas un t_nodo estas pasando el puntero del nodo, por tanto no hace falta que lo desreferencies para luego pasar la dirección de memoria en el main y lo mismo. Si lo declaras asi:
void agregar(t_nodo &, t_dato);
Te evitas poner & en el main y queda más fácil de leer.
Cuarto: Por lo que he visto, podrías usar un puntero fin para evitar el coste de O(n) que supone recorrer toda la lista. Como no hay clases en C podrias crear una struct extra:
struct s_nodo_ini
{
t_dato dato;
struct s_nodo*sig;
struct s_nodo *fin;
}
para el nodo cabeza y cuando añades un nodo al fin lo haces desde fin y luego actualizas el nodo fin y si quieres recorrer toda la lista lo haces desde el nodo sig.
En cuestión a tu problema: usa el nodo aux para moverte, no hace falta usar recursividad de forma innecesaria.
void eliminar(t_nodo*nodo,char*texto)
{
t_nodo aux= &nodo; //siendo nodo la cabeza/inicio
while(aux != NULL) //recorres todo la lista
{
//Aqui haces la comprobación y en caso positivo lo eliminas
aux = aux->sig; //no se si se escribe asi en C pero el concepto es el mismo
}
}