UTNianos

Versión completa: [Funciones de C] Lista doblemente enlazada
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
Páginas: 1 2
Les dejo andando varias funciones de doble enlazada... Me falta el ordenar, mañana lo hago y edito!!!

Exitos!=D


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

#define MAX_CARACTERES 20
#define SALIR 0
#define OK 1
#define ERROR -1

typedef struct nodo{
char elemento[MAX_CARACTERES];
struct nodo *siguiente;
struct nodo *anterior;
}NODO;

int menu(void);
int agregar_principio(NODO **lista);
char *gets_s(char *s, int size);
void listar(NODO *lista);
int agregar_final(NODO **lista);
int cant_elementos(NODO *lista);
int borrar_primer_elemento(NODO **lista);
int borrar_ultimo_elemento(NODO **lista);
void elimiar_lista(NODO **lista);
void salir(NODO **lista);
int guardar_lista(NODO *lista);
NODO * cargar_lista(void);
int guardar_dato_archivo(NODO **lista,NODO dato_nuevo);
int borrar_elemento(NODO **lista);
int ordenar_lista(NODO **lista);
void quitar_elemento(NODO **aux,char *elemento);
int agregar_ordenado(NODO **lista_ordenada,char *elemento);


int main(void){

NODO *lista = NULL;
int opcion;
int cantidad;

printf("-------------------------\n");
printf("- Bienvenido al sistema -\n");
printf("-------------------------\n");

do{
opcion = menu();
switch(opcion){
case 1: agregar_principio(&lista); break;
case 2: agregar_final(&lista); break;
case 3: borrar_primer_elemento(&lista); break;
case 4: borrar_ultimo_elemento(&lista); break;
case 5: borrar_elemento(&lista); break;
case 6: cantidad = cant_elementos(lista); break;
case 7: ordenar_lista(&lista); break;
case 8: listar(lista); break;
case 9: elimiar_lista(&lista);break;
case 10: guardar_lista(lista); break;
case 11: lista = cargar_lista(); break;
case 0: salir(&lista);break;
default: printf("Opcion incorrecta");break;
}
}while(opcion!=SALIR);
puts("Fin del programa");
getchar();
getchar();
return(1);
}


int menu(void){

int opcion;

printf("--------------------\n");
printf("- Menu del sistema -\n");
printf("--------------------\n");

printf("\n\t1- Agregar elemento al principio de la lista.\n"
"\t2- Agregar elemento al final de la lista.\n"
"\t3- Borrar primer elemento de la lista.\n"
"\t4- Borrar ultimo elemento de la lista.\n"
"\t5- Borrar un elemento determinado de la lista.\n"
"\t6- Cantidad de elementos de la lista.\n"
"\t7- Ordenar lista.\n"
"\t8- Listar lista.\n"
"\t9- eliminar lista.\n"
"\t10- Guardar lista (testeando).\n"
"\t11- Cargar lista (testeando).\n"
"\t0- Salir del programa.\n\n");
scanf("%d",&opcion);
return(opcion);
}



int agregar_principio(NODO **lista){

NODO *nuevo_dato = NULL;
char nombre_aux[MAX_CARACTERES];
NODO *aux = NULL; //Para no tener problemas con el doble puntero en struct.

aux = *lista;

//Cargo y seteo los valores del nuevo elemento en la lista.
nuevo_dato = (NODO*) malloc(sizeof(NODO));
if(nuevo_dato == NULL){
printf("Error en el pedido de memoria");
return(ERROR);
}
getchar();
printf("Ingrese el nombre del elemento a guardar: ");
gets_s(nombre_aux,MAX_CARACTERES);
strcpy(nuevo_dato->elemento,nombre_aux);
nuevo_dato->siguiente = NULL;
nuevo_dato->anterior = NULL;

/***************************************************************/

if(*lista == NULL){ //Primer elemento de la lista..
*lista = nuevo_dato;
}
else{ //si ya había elementos cargados..
nuevo_dato->siguiente = aux;
nuevo_dato->anterior = aux->anterior;
aux->anterior = nuevo_dato;
aux = nuevo_dato;
*lista = aux;
}
return(OK); //Todo salio bien.
}

int agregar_final(NODO **lista){

NODO *nuevo_dato = NULL;
char nombre_aux[MAX_CARACTERES];
NODO *aux = NULL; //Para no tener problemas con el doble puntero en struct.

aux = *lista;

//Cargo y seteo los valores del nuevo elemento en la lista.
nuevo_dato = (NODO*) malloc(sizeof(NODO));
if(nuevo_dato == NULL){
printf("Error en el pedido de memoria");
return(ERROR);
}
getchar();
printf("Ingrese el nombre del elemento a guardar: ");
gets_s(nombre_aux,MAX_CARACTERES);
strcpy(nuevo_dato->elemento,nombre_aux);
nuevo_dato->siguiente = NULL;
nuevo_dato->anterior = NULL;

/***************************************************************/

if(*lista == NULL){ //unico elemento..
*lista = nuevo_dato;
}
else{ //Si no es el unico elemento
while(aux->siguiente != NULL){
aux = aux->siguiente;
}
nuevo_dato->siguiente = aux->siguiente;
nuevo_dato->anterior = aux;
aux->siguiente=nuevo_dato;
}
return(OK);
}


void listar(NODO *lista){

if(lista == NULL){
printf("No hay elementos cargados en la lista aun\n");
}
else{ //Si hay elementos cargados en la lista:
do{
printf("Elemento: %s\n",lista->elemento);
lista = lista->siguiente;
}while(lista!=NULL);
}
}

int cant_elementos(NODO *lista){

int cantidad=0;

if(lista == NULL){
puts("No hay elementos en la lista");
return(ERROR);
}
else{
while(lista!=NULL){
cantidad ++;
lista = lista->siguiente;
}
printf("Cantidad de datos en la lista: %d\n",cantidad);
return(cantidad);
}
}


int borrar_primer_elemento(NODO **lista){

NODO *buffer = NULL; //guardo el que voy a borrar
NODO *aux = NULL; //Para no tener problemas con el doble puntero en estructuras

if(*lista == NULL){ //Si no hay elementos en la lista, no tiene para borrar
puts("No hay elementos en la lista!\n");
return(ERROR);
}
aux = *lista;
if(aux->siguiente == NULL){ //Unico elemento en la lista.
*lista = NULL;
free(aux);
return(OK);
}
else{ //Mas de un elemento a borrar.
buffer = *lista; //lo guardo para el free.
aux = *lista;
aux = aux->siguiente;
aux->anterior = buffer->anterior; // (NULL)
free(buffer);
*lista = aux;
return(OK);
}
}


int borrar_ultimo_elemento(NODO **lista){

NODO *aux = NULL; //Para no perder la referencia.
NODO *buffer = NULL; //Aca almaceno el nodo a liberar.

if(*lista == NULL){
puts("La lista esta vacia");
return(OK);
}
aux = *lista;
while(aux->siguiente!=NULL){
aux = aux->siguiente;
}
buffer = aux;
aux->anterior->siguiente = aux->siguiente; //(NULL)
free (buffer);
}


void elimiar_lista(NODO **lista){

NODO *aux = NULL; //Para recorrer la lista.
NODO *buffer = NULL; //El que uso para borrar cada elemento.

if(*lista == NULL){ //Si no hay elementos en la lista no hay que borrar.
puts("No hay elementos cargados en la lista");
}
else{ //Si hay elementos, los elimino uno a uno :)
aux = *lista;
while(aux != NULL){
buffer = aux;
aux = aux->siguiente;
free(buffer);
}
*lista = NULL;
}
}


void salir(NODO **lista){

NODO *aux = NULL; //Para recorrer la lista.
NODO *buffer = NULL; //El que uso para borrar cada elemento.

if(*lista == NULL){ //Si no hay elementos en la lista no hay que borrar.
puts("No hay elementos cargados en la lista");
}
else{ //Si hay elementos, los elimino uno a uno :)
aux = *lista;
while(aux != NULL){
buffer = aux;
aux = aux->siguiente;
free(buffer);
}
*lista = NULL;
}
}


int guardar_lista(NODO *lista){

FILE *fp;
NODO *aux = NULL;

fp = fopen("Lista_Doble.txt","a+");
if(fp == NULL){
puts("Error al abrir el archivo");
return(ERROR);
}
while(lista!=NULL){
fwrite(lista,sizeof(NODO),1,fp);
lista = lista->siguiente;
}
fclose(fp);
return(OK);
}


NODO * cargar_lista(void){

NODO* lista = NULL;
NODO dato_nuevo; //Aca guardo el nodo que recibo desde el archivo.
FILE *fp;

fp = fopen("Lista_Doble.txt","a+");
if(fp == NULL){
puts("Error al abrir el archivo");
return(ERROR);
}
while(!feof(fp)){
fread(&dato_nuevo,sizeof(NODO),1,fp);
guardar_dato_archivo(&lista,dato_nuevo);
}
fclose(fp);
return(lista);
}


int guardar_dato_archivo(NODO **lista,NODO dato_nuevo){

NODO *nuevo_dato = NULL;
NODO *aux = NULL;

nuevo_dato = (NODO*) malloc(sizeof(NODO));
if(nuevo_dato == NULL){
puts("Error al pedir memoria");
return(ERROR);
}

nuevo_dato->siguiente = NULL;
nuevo_dato->anterior = NULL;
strcpy(nuevo_dato,dato_nuevo.elemento);

/********************************************/

if(*lista == NULL){ //Todavía no cargue ningun nodo..
*lista = nuevo_dato;
return(OK);
}
else{
aux = *lista;
nuevo_dato->siguiente = aux;
nuevo_dato->anterior = aux->anterior; //(NULL)
aux->anterior = nuevo_dato;
aux = nuevo_dato;
*lista = aux;
return(OK);
}
}


int borrar_elemento(NODO **lista){

NODO dato_borrar;
NODO* aux = NULL;
NODO* buffer = NULL; //Este lo uso como buffer del elemento a eliminar.
getchar();
puts("Ingrese el dato a borrar: ");
gets_s(dato_borrar.elemento,MAX_CARACTERES);

if(*lista == NULL){
puts("La lista esta vacia senor");
return(OK);
}
/* Empiezo la comparacion */
aux = *lista;
while((aux!=NULL)&&(strcmp(aux->elemento,dato_borrar.elemento)!=0)){
aux = aux->siguiente;
}
if(aux == NULL){
puts("No se encontro el dato buscado");
return(ERROR);
}
if((aux->siguiente == NULL)&&(aux->anterior==NULL)){ //Si hay un solo elem.
free(aux);
*lista = NULL;
return(OK);
}
if(aux->anterior == NULL){ //primer elemento de la lista..
buffer = aux;
aux->siguiente->anterior = aux->anterior; // (NULL)
aux = aux->siguiente;
*lista = aux;
free(buffer);
return(OK);
}
if(aux->siguiente == NULL){ //Si es el ultimo..
buffer = aux;
aux->anterior->siguiente = aux->siguiente;
free(buffer);
return(OK);
}

//Si es un bloque que este por el medio..
buffer = aux; //Es el que tengo que eliminar.
aux->anterior->siguiente = aux->siguiente;
aux->siguiente->anterior = aux->anterior;
free(buffer); //Tambien se puede borrar aux....
return(OK);
}



char *gets_s(char *s, int size){
int len;

if (!fgets(s, size, stdin)){
if (size > 0)
s[0] = '\0';
return NULL;
}
else{
len = strlen(s);
if (len && s[len-1] == '\n')
s[len-1] = '\0';
return s;
}
}

int ordenar_lista(NODO **lista){

NODO *aux = NULL;
NODO *lista_ordenada = NULL; //Aca voy guardando la nueva lista ordenada.
char dato_retirado[MAX_CARACTERES];

if(*lista == NULL){
puts("No hay elementos en la lista");
return(ERROR);
}
aux = *lista;
while(aux!=NULL){
quitar_elemento(&aux,dato_retirado);
agregar_ordenado(&lista_ordenada,dato_retirado);
}
*lista = lista_ordenada;
return(OK);
}

void quitar_elemento(NODO **aux,char *elemento){

NODO *siguiente_dato = NULL; //Para no tener problemas en el avance de list.
NODO *buffer = NULL; //Nodo a eliminar de la lista.

siguiente_dato = *aux;
buffer = *aux;

strcpy(elemento,buffer->elemento);
*aux = siguiente_dato->siguiente;
free(buffer);
}


int agregar_ordenado(NODO **lista_ordenada,char *elemento){

NODO *aux = NULL;
NODO *ant = NULL;
NODO *nuevo_dato = NULL;

nuevo_dato = (NODO*) malloc(sizeof(NODO));
if(nuevo_dato == NULL){
puts("Error al pedir memoria");
return(ERROR);
}
strcpy(nuevo_dato->elemento,elemento);
nuevo_dato->siguiente = NULL;
nuevo_dato->anterior = NULL;

/* Hasta aca solo cargue la estructura dato (nodo) de la lista */

if(*lista_ordenada == NULL){ //Si la lista esta vacia.
*lista_ordenada = nuevo_dato;
return(OK);
}//De lo contrario agrego el nodo ordenado.

aux = *lista_ordenada;

while((aux != NULL)&&(strcmp(aux->elemento,elemento)<0)){
ant = aux;
aux = aux->siguiente;
}
if(ant == NULL){//un solo elemento.
nuevo_dato->siguiente = aux;
nuevo_dato->anterior = aux->anterior;
aux->anterior = nuevo_dato;
*lista_ordenada = nuevo_dato;
return(OK);
}

if(aux == NULL){ //Ultimo elemento de la lista.
ant->siguiente = nuevo_dato;
nuevo_dato->anterior = ant;
nuevo_dato->siguiente = aux;
return(OK);
}
//Si no es porque esta en el medio!

nuevo_dato->siguiente = aux;
aux->anterior = nuevo_dato;
nuevo_dato->anterior = ant;
ant->siguiente = nuevo_dato;
return(OK);
}




justo en lo que andaba gracias.

pd:una consulta como toman el tema sockets en los finales? te dicen que ya tenes funciones armadas que te permiten manejarlos casi como un file mas o hay que desarrollar estas desde 0?
Yo no me presente todavía, le mande un mail a mi profesor preguntandole y me contesto: que era medio raro, que por lo general siempre dan las funciones y el .h a incluir... pero que hay algunos alumnos que optan por desarrollar todo a pedal, que no esta clara la cosa...

Yo por mi parte voy a manejar las funciones de la "cátedra" que me mandaron un alumno de furfaro... y se que en unos de los finales se las dejaron usar =)
Estudiarse esas estructuras de memoria son un parto.

Saludos!
Bueno estoy intentando hacer funcionar el ordenamiento por intercambio de enlaces y no funciona.. estoy podrído(?)
Estoy hace 3 horas y nada... alguno tiene alguna idea que puede estar fallando?



int ordenar_lista(NODO **lista){

NODO *aux = NULL;
NODO *lista_ordenada = NULL; //Aca voy guardando la nueva lista ordenada.
char dato_retirado[MAX_CARACTERES];

if(*lista == NULL){
puts("No hay elementos en la lista");
return(ERROR);
}
aux = *lista;
while(aux!=NULL){
quitar_elemento(&aux,dato_retirado);
agregar_ordenado(&lista_ordenada,dato_retirado);
}
*lista = lista_ordenada;
return(OK);
}

void quitar_elemento(NODO **aux,char *elemento){

NODO *siguiente_dato = NULL; //Para no tener problemas en el avance de list.
NODO *buffer = NULL; //Nodo a eliminar de la lista.

siguiente_dato = *aux;
buffer = *aux;

strcpy(elemento,buffer->elemento);
*aux = siguiente_dato->siguiente;
free(buffer);
}


int agregar_ordenado(NODO **lista_ordenada,char *elemento){

NODO *aux = NULL;
NODO *ant = NULL;
NODO *nuevo_dato = NULL;

nuevo_dato = (NODO*) malloc(sizeof(NODO));
if(nuevo_dato == NULL){
puts("Error al pedir memoria");
return(ERROR);
}
strcpy(nuevo_dato->elemento,elemento);
nuevo_dato->siguiente = NULL;
nuevo_dato->anterior = NULL;

/* Hasta aca solo cargue la estructura dato (nodo) de la lista */
aux = *lista_ordenada;

if(*lista_ordenada == NULL){ //Si la lista esta vacia.
*lista_ordenada = nuevo_dato;
return(OK);
}//De lo contrario agrego el nodo ordenado.

while((aux != NULL)||(strcmp(aux->elemento,elemento)<0)){
ant = aux;
aux = aux->siguiente;
}

if(ant == NULL){//un solo elemento.
nuevo_dato->siguiente = aux;
nuevo_dato->anterior = aux->anterior;
aux->anterior = nuevo_dato;
*lista_ordenada = nuevo_dato;
return(OK);
}

if(aux == NULL){ //Ultimo elemento de la lista.
ant->siguiente = nuevo_dato;
nuevo_dato->anterior = ant;
nuevo_dato->siguiente = aux;
return(OK);
}
//Si no es porque esta en el medio!

nuevo_dato->siguiente = aux;
aux->anterior = nuevo_dato;
nuevo_dato->anterior = ant;
ant->siguiente = nuevo_dato;
return(OK);
}


Ya lo arregle, dejo todo el código funcionando en primer post!
ustedes que la tienen mas clara con que libro preparan la materia durante la cursada acá recomiendan el deitel y deitel.
el año pasado la tuve que dejar pero la materia acá es mucho mas fácil que allá.


gracias ;)
Mira yo me lei todo el deitel durante la cursada, y ahora para preparar el final lo volví a leer XD
Igual son lecturas rápidas.. ponele que lo leí en 4 días...
Aprender se aprende programando y tirando código...

También use el K&R para la parte de vector de punteros y matrices que NO ME SALIA y el deitel lo explica mal... y use: http://c.conclase.net/edd/index.php?cap=005 para la parte de listas (Y)

De última si no te sale algo pasa a preguntar y vemos si te podemos ayudar =)
ok gracias Feer por la info thumbup3
Creo que el ordenamiento te la complicaste demasiado y mas si es solo por un elemento, yo uso siempre el método de burbuja, nose si lo conoces.
Jajaja, si, puede ser, igualmente ya pude arreglarla y cumple doble función! ingreso nuevos nodos y después también me sirve para ordenar, 2 en 1(?)
Igual.. para ordenar una lista doble enlazada utilizando burbujeo, previamente es necesario tener una funcion que haga el intercambio entre los enlaces (swap le dicen, y no recomiendo meterse en esa travesia para nada).

Sino recaes en intercambiar el contenido de las listas, y en muchos finales se aclara que eso no se puede hacer.
Que? y tampoco puedo intercambiar los punteros?.
Si, y de eso se trata justamente la funcion de swap (intercambio).
Pero es un bardo.. La tengo por ahi si queres verla.

Lo mejor es lo que hizo feer.
Ir agregando cada nodo de la lista desordenada en una lista nueva, por medio de una funcion que inserte los nodos ordenados por algun campo e ir eliminando cada nodo de la lista vieja (aunque podes eliminarla toda junta con esa funcion recursiva que son 2 lineas).

Sino, tambien podes intercambiar el contenido de los nodos..
Pero imaginate que no es muy versatil hacer eso, y por eso en algun que otro final te dicen que no lo hagas asi.
Por qué no quieren?
Lo único que haces es usar una estructura auxiliar que podes declararlo como puntero si queres. Luego le haces free() y listo, no desperdicias ningún espacio de memoria.
Y si me obligan a no intercambiar el contenido, pues prefiero el bardo, me declaro una cadena de punteros y los guardo.
Imaginate que tenes que ordenar una lista donde cada nodo tiene un millon de elementos, vas a copiar campo por campo..
Es mucho desperdicio.
De la otra manera el programa es el mismo venga lo que venga adentro de cada nodo.

Supongo que lo harán por eso.
(18-02-2013 21:58)JulianD escribió: [ -> ]Imaginate que tenes que ordenar una lista donde cada nodo tiene un millon de elementos, vas a copiar campo por campo..
Es mucho desperdicio.
De la otra manera el programa es el mismo venga lo que venga adentro de cada nodo.

Supongo que lo harán por eso.

Si cada nodo tiene un millón de elementos o demasiados, no copio campo por campo sino la estructura completa como con cualquier variable. A lo sumo tendría que guardar los nodos "siguiente" y "anterior" y reubicarlos. No creo que la igualación de una variable haga una gran diferencia con su tamaño, ojo, no estoy seguro.
Por otro lado, buscar cada nodo para luego reubicarlo en una nueva lista me suena a demasiado trabajo. ¿Te imaginas realizar una nueva lista solo por intercambiar 2 nodos luego de que por cada "for" se busque el próximo nodo a agregar?.
Sé que es solo es mi opinión.
Sin embargo, encontré una forma de realizarlo agregando y borrando el nodo correspondiente.
Páginas: 1 2
URLs de referencia