Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: m@o_614 en 29 Mayo 2012, 18:49 pm



Título: listas simplemente enlazadas
Publicado por: m@o_614 en 29 Mayo 2012, 18:49 pm
Saludos estoy haciendo el siguiente codigo de listas enlazadas que me ingresen datos por el final de la lista, todavia me cuesta trabajo comprender esto de las listas y es por eso que solamente tengo una funcion de los cases hecha, pero me marca errores como:

dereferencing pointer to incomplete type y no entiendo que es lo que estoy haciendo mal

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef struct info
  5. {
  6.    int dato;
  7.    struct lista *sig;
  8. }L;
  9.  
  10. void insertar_final(int x,L *lista);
  11.  
  12. int main()
  13. {
  14.    L *lista;//Aqui coloco el puntero hacia la estructura
  15.    lista= NULL;//Lo inicializo en NULL para indicar que esta vacia
  16.    int opcion,continuar=1,x;
  17.    do
  18.    {
  19.        printf("Menu!\n");
  20.        printf("1) Insertar al final\n");
  21.        printf("2) Mostrar lista\n");
  22.        printf("3) Buscar elemento\n");
  23.        printf("4) Busqueda recursiva\n");
  24.        printf("5) Contar elementos en la lista\n");
  25.        printf("6) Salir\n");
  26.        scanf("%d",&opcion);
  27.        switch(opcion)
  28.        {
  29.            case 1:
  30.               printf("Dame el dato que deseas insertar:\n");
  31.               scanf("%d",&x);
  32.               insertar_final(x,lista);//le paso el dato que deseo colocar como primer nodo y el puntero
  33.               break;
  34.            case 2:
  35.               //no lo he terminado
  36.               break;
  37.            case 3:
  38.            //no lo he terminado
  39.               break;
  40.            case 4:break;
  41.            //no lo he terminado
  42.            case 5:break;
  43.            //no lo he terminado
  44.            case 6:
  45.               continuar=0;
  46.               break;
  47.            default:
  48.               printf("Opcion no valida\n");
  49.        }
  50.    }while(continuar);
  51.    return 0;
  52. }
  53.  
  54. void insertar_final(int x,L *lista)
  55. {
  56.    L *ultimo;//otro puntero ahora hacia el ultimo nodo
  57.    ultimo->sig=(L*)malloc(sizeof(L));//le asigno memoria (creo nuevo nodo)
  58.    ultimo->sig->dato= x;//le asigno el elemento que queria
  59.    ultimo->sig->sig=NULL;
  60.    ultimo= ultimo->sig;
  61. }


Título: Re: listas simplemente enlazadas
Publicado por: durasno en 29 Mayo 2012, 21:16 pm
Hola! el problema es q vos declaras un puntero "ultimo" pero no le reservas memoria, lo que estas haciendo es reservar memoria al siguiente de ultimo lo cual esta mal. Una pregunta ¿¿para que intentas reservar al siguiente?? no es mejor hacer:
Código
  1. void insertar_final(int x,L *lista)
  2. {
  3.    L *ultimo;//otro puntero ahora hacia el ultimo nodo
  4.    ultimo=(L*)malloc(sizeof(L));//le asigno memoria (creo nuevo nodo)
  5.    ultimo->dato= x;//le asigno el elemento que queria
  6.    ultimo->sig=NULL;
  7. }
De todas formas el error principal es q no estas enlazando la lista. Una forma de resolver es hacer:
Código
  1.            case 1:
  2.               printf("Dame el dato que deseas insertar:\n");
  3.               scanf("%d",&x);
  4.               lista=insertar_final(x,lista);
  5.               breaK;
  6.       ...................
  7.  
  8. struct info * insertar_final(int x,L *lista)
  9. {
  10.    L *ultimo;//otro puntero ahora hacia el ultimo nodo
  11.    ultimo=(L*)malloc(sizeof(L));//le asigno memoria (creo nuevo nodo)
  12.    ultimo->dato= x;//le asigno el elemento que queria
  13.    ultimo->sig=NULL;
  14.  
  15.   if(lista==NULL) /* si la lista esta vacia */
  16.       return ultimo;
  17.  
  18.   else {
  19.        while(lista->sig!=NULL) /* busco el ultimo nodo */
  20.              lista=lista->sig; /* cambio al siguiente nodo */
  21.        lista->sig=ultimo; /* el ultimo de la lista apunta al "ultimo" creado en esta funcion */
  22.   }
  23. }
Solo es necesario retornar "ultimo" cuando la lista esta vacia. En el bucle lo que hice es buscar el ultimo nodo y enlazarlo al puntero "ultimo". No lo compile pero deberia funcionar

Saludos


Título: Re: listas simplemente enlazadas
Publicado por: m@o_614 en 31 Mayo 2012, 21:05 pm
Saludos durasno respondiendo a tu pregunta lo que pasa es que como ultimo ya lo habia declarado como apuntador pensé que reservandole memoria en

    ultimo->sig

lo que estaba haciendo era creando un nuevo nodo que estuviera enlazado al campo sig del apuntador ultimo, no se si me di a entender??? :-\  o sea que crei que ultimo al momento de declararlo como apuntador era un nodo que tenia un campo dato y un enlace sig, pense que con tan solo hacer esto:

    L *ultimo;
 ya tenia la direccion de una estructura

entendi bien?? No se si este es mi principal error

saludos y gracias


Título: Re: listas simplemente enlazadas
Publicado por: durasno en 1 Junio 2012, 06:43 am
Como vos decis
Citar
este es mi principal error
Declarar un puntero a la estructura no implica que ya puedas hacer uso de los campos de la struct, siempre a un puntero le tenes q asignar algo. En otras palabras un puntero no es mas que una variable, y como toda variable(int, float....) le tenes q asignar algo. Lo q vos hiciste equivale a hacer:
Código
  1. int a,c;
  2. int b=10;
  3. c=b + a; // y esto q da como resultado????

Espero se haya entendido. Saludos


Título: Re: listas simplemente enlazadas
Publicado por: 0xDani en 1 Junio 2012, 16:07 pm
Espera, L * ultimo. Un puntero a L?Que tipo es ese? Que alguien me lo explique, por favor.

Saludos ;D


Título: Re: listas simplemente enlazadas
Publicado por: Ferno en 1 Junio 2012, 16:50 pm
Espera, L * ultimo. Un puntero a L?Que tipo es ese? Que alguien me lo explique, por favor.

Saludos ;D

Fijate que la declaración del struct es de esta manera:

Código
  1. typedef struct info
  2. {
  3.    int dato;
  4.    struct lista *sig;
  5. }L;

Luego de cerrar con llaves, existe la posibilidad (porque si quieres lo puedes omitir) de escribirle un nombre al tipo que definiste para reconocerlo fácilmente (puesto que es un nombre que escribiste vos) y no tener que escribir "struct info" cada vez que quieres utilizar el tipo en alguna declaración.
En este código, "L" hace referencia al tipo "struct info".


Título: Re: listas simplemente enlazadas
Publicado por: 0xDani en 3 Junio 2012, 14:45 pm
Ah Ok, no lo habia visto.


Título: Re: listas simplemente enlazadas
Publicado por: m@o_614 en 5 Junio 2012, 03:06 am
Aqui ya dividi la tarea de agregar nodos con las funciones insertar_final y nuevo_nodo (es la que crea el nodo) pero todavia no me queda claro para que utilizar el apuntador lista, si fuera una lista que inserte por el encabezado sería un poco más fácil, pero como en insertar al final no tengo un puntero que me apunte al ultimo nodo y tengo que recorrer la lista y despues insertar

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #define MAX 10
  5.  
  6. typedef struct info
  7. {
  8.    int dato;
  9.    struct info *sig;
  10. }L;
  11.  
  12. void insertar_final(int i,L **lista);
  13. L *nuevo_nodo(int i);
  14.  
  15. int main()
  16. {
  17.    L *lista;
  18.    lista= NULL;//inicializo la lista vacia
  19.    srand(time(NULL));
  20.    int opcion,continuar=1,i;
  21.    do
  22.    {
  23.        printf("Menu!\n");
  24.        printf("1) Insertar al final\n");
  25.        printf("2) Mostrar lista\n");
  26.        printf("3) Buscar elemento\n");
  27.        printf("4) Busqueda recursiva\n");
  28.        printf("5) Contar elementos en la lista\n");
  29.        printf("6) Salir\n");
  30.        scanf("%d",&opcion);
  31.        switch(opcion)
  32.        {
  33.            case 1:
  34.               for(i=(rand()%MAX+1);i;)
  35.                  insertar_final(i,&lista);
  36.               break;
  37.            case 2:
  38.               break;
  39.            case 3:
  40.            //no lo he terminado
  41.               break;
  42.            case 4:break;
  43.            //no lo he terminado
  44.            case 5:break;
  45.            //no lo he terminado
  46.            case 6:
  47.               continuar=0;
  48.               break;
  49.            default:
  50.               printf("Opcion no valida\n");
  51.        }
  52.    }while(continuar);
  53.    return 0;
  54. }
  55.  
  56. void insertar_final(int i,L **lista)
  57. {
  58.    L *ultimo;
  59.    ultimo= nuevo_nodo(i);
  60.    if(ultimo->sig!=NULL)//aqui recorro la lista hasta encontrar NULL
  61.        ultimo=ultimo->sig;
  62.    ultimo->sig= *lista;//aqui ya encontro NULL entonces lo apunto con lista
  63. }
  64.  
  65. L *nuevo_nodo(int i)
  66. {
  67.    L *nuevo;
  68.    nuevo= (L*)malloc(sizeof(L));
  69.    nuevo->dato= i;
  70.    nuevo->sig= NULL;
  71.    return nuevo;
  72. }
  73.  
  74.  
saludos


Título: Re: listas simplemente enlazadas
Publicado por: durasno en 5 Junio 2012, 07:31 am
Hola! tal vez si te hicieras algunos graficos entenderias un poco mejor... Con esto:
Código
  1. if(ultimo->sig!=NULL)//aqui recorro la lista hasta encontrar NULL
  2.        ultimo=ultimo->sig;
no estas recorriendo la lista, es con while. Igual esta mal vos no podes recorrer la lista con el puntero ultimo(ultimo no es la lista); la lista es el puntero "lista"

Y con esto:
Código
  1. ultimo->sig= *lista;//aqui ya encontro NULL entonces lo apunto con lista
no estas haciendo que ultimo se coleque al final de la lista sino al principio; igual la logica tambien esta mal

Fijate el codigo q te pase antes, si bien no use puntero a puntero, lo podes hacer vos solo cambiando algunas cosas

Saludos


Título: Re: listas simplemente enlazadas
Publicado por: m@o_614 en 8 Junio 2012, 02:35 am
Saludos

aqui ya el código no me marca errores ni me saca del programa como antes, pero no hace nada. Si te fijas es casi el mismo código que el tuyo

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #define MAX 10
  5.  
  6. typedef struct info
  7. {
  8.    int dato;
  9.    struct info *sig;
  10. }L;
  11.  
  12. void insertar_final(int i,L *lista);
  13. L *nuevo_nodo(int i);
  14.  
  15. int main()
  16. {
  17.    L *lista;
  18.    lista= NULL;//inicializo la lista vacia
  19.    srand(time(NULL));
  20.    int opcion,continuar=1,i;
  21.    do
  22.    {
  23.        printf("Menu!\n");
  24.        printf("1) Insertar al final\n");
  25.        printf("2) Mostrar lista\n");
  26.        printf("3) Buscar elemento\n");
  27.        printf("4) Busqueda recursiva\n");
  28.        printf("5) Contar elementos en la lista\n");
  29.        printf("6) Salir\n");
  30.        scanf("%d",&opcion);
  31.        switch(opcion)
  32.        {
  33.            case 1:
  34.               for(i=(rand()%MAX+1);i;)
  35.                  insertar_final(i,lista);
  36.               break;
  37.            case 2:
  38.               break;
  39.            case 3:
  40.            //no lo he terminado
  41.               break;
  42.            case 4:break;
  43.            //no lo he terminado
  44.            case 5:break;
  45.            //no lo he terminado
  46.            case 6:
  47.               continuar=0;
  48.               break;
  49.            default:
  50.               printf("Opcion no valida\n");
  51.        }
  52.    }while(continuar);
  53.    return 0;
  54. }
  55.  
  56. void insertar_final(int i,L *lista)
  57. {
  58.    L *ultimo;
  59.    ultimo= nuevo_nodo(i);
  60.  
  61.    if(lista==NULL)
  62.       lista=ultimo;
  63.    while(lista->sig!=NULL)
  64.       lista=lista->sig;
  65.    lista->sig=ultimo;
  66. }
  67.  
  68. L *nuevo_nodo(int i)
  69. {
  70.    L *nuevo;
  71.    nuevo= (L*)malloc(sizeof(L));
  72.    nuevo->dato= i;
  73.    nuevo->sig= NULL;
  74.    return nuevo;
  75. }
  76.  
  77.  

gracias


Título: Re: listas simplemente enlazadas
Publicado por: durasno en 8 Junio 2012, 07:28 am
Vos mismo lo dijiste es casi igual, pero no lo es... Fijate en el if de insertar_final() pregunto si lista es NULL(lista vacia), si es verdadero retorno la estructura creada. (ademas t falta un else :P)

Si vos pasas de esta manera el puntero:
Código
  1. insertar_final(i,lista); // llamada  a la funcion
cuando lista regrese al main no va a hacer ningun cambio, esto es porque el puntero se paso por valor. Podes hacer dos cosas: retornar una estructura como lo hic antes o pasar el puntero por referencia, ¿como? pasando la direccion del puntero
Código
  1. insertar_final(i,&lista); // paso la direccion
  2. ......................
  3. void insertar_final(int i,L **lista)
  4. {
  5.    L *ultimo;
  6.    ultimo= nuevo_nodo(i);
  7.  
  8.    if(*lista==NULL) /* lista vacia */
  9.       *lista=ultimo;
  10.    else {
  11.       L *aux=*lista; /* creo un puntero auxiliar para q me recorra la lista */
  12.       while(aux->sig!=NULL) /* recorro la lista */
  13.           aux=aux->sig; /* cambia al siguiente nodo */
  14.       aux->sig=ultimo; /* el ultimo de la lista apunta a "ultimo" creado aca
  15.     }
  16. }
Fijate que creo un puntero auxiliar para recorrer la lista; esto es porque si vos usas el puntero lista vas a perder la referencia al primer nodo lo cual no es bueno... Cualquier duda segui pregutando

Saludos