[C con Clase] error lista simple

Salvador Pozo salvador en conclase.net
Lun Sep 8 17:35:40 CEST 2008


El pasado 2008-09-08 14:59:50, batista escribió:

::: Lo siento, he enviado el mensaje anterior por error sin terminar. :::
 
b> hola a todos tengo un problema con el algoritmo de lista simple, primero ke
b> nada no me sugieran ver el algoritmo de la pagina de c.conclase pues es
b> muylargo y enredado, he tratado de implementar mi algoritmo guiandome de un
b> arbol binario ke me parecio mas facil y corto de entender.

Hola:

Pues a pesar de que no quieras que lo haga, te sugiero que intentes comprender el algoritmo de la página de C con Clase. Le dediqué mucho tiempo para intentar que quedase claro, y me entristece ver que no te ha gustado :-'(

En tu código he encontrado cuatro errores que hacen imposible que funcione correctamente.

1) En el caso de la inserción en una lista vacía:

b> void insertar()
b> {
b>     cantidad *nuevo;
b>     nuevo = new cantidad;
b>     if(primera == NULL)
b>     {
b>         primera = nuevo;
b>         nuevo->numero = 15;
b>         nuevo->sig = ultimo;
b>     }

Te falta un paso. Al finalizar la inserción primera y ultimo deberían apuntar al nuevo nodo, ya que la lista sólo tendrá un nodo.

Por lo tanto, es imprescindible que actualices el valor de ultimo para que apunte a primera o a nuevo (el resultado es el mismo):

        ultimo=primera;

De otro modo, en la siguiente inserción ultimo seguiría valiendo NULL, y aunque parece que esto no le importe a tu programa, tal como está, eso nos lleva al segundo error, que está en el caso de sucesivas inserciones:

b>     else
b>     {
b>         ultimo = nuevo;
b>         nuevo->numero = 15;
b>         nuevo->sig = NULL;
b>     }
b> }

2) En este caso, está claro que insertas el nuevo nodo al final de la lista, pero no enlazas la lista con el nuevo nodo. Falta que el nodo que hasta ahora era el último tenga como "siguiente" al nuevo nodo. De otro modo, el nuevo nodo queda aislado de la lista.

Hay que insertar la línea:

        ultimo->sig = nuevo;

Justo antes de "ultimo=nuevo;".

Para que esto funcione, ultimo no debe valor NULL, que era el valor que tendría si no corregimos el primer error.

Por coherencia, la condición para averiguar si la lista está vacía debería ser 
if(ultimo == NULL), ya que el caso más peligroso es asignar valores a un objeto apuntado por un puntero nulo, y eso sólo se presenta en el caso del puntero ultimo, concretamente al hacer "ultimo->sig = nuevo;".

3) Los otros dos errores están en la función "recuperar".

b>     while(actual->sig != NULL)

Con esta condición nunca visitaremos el último nodo, ya que el bucle terminará cuando el siguiente al actual sea nulo, es decir, cuando actual apunte al último nodo. Pero ese nodo no se analizará, ya que el valor de "actual", se actualiza al final del bucle.

b>     {
b>         printf("el numero es %i", actual->numero);

4) El último error es que no puedes avanzar en una lista enlazada usando el operador ++, al menos no en C, y desde luego, nunca si no se sobrecarga ese operador.

b>         actual++;

Lo que hace esta sentencia es incrementar el puntero actual, de modo que apunte a la dirección de memoria del siguiente objeto "cantidad", pero eso, casi con total seguridad, no será la dirección del siguiente nodo de la lista.

Esta sentencia se debe sustituir por:

        actual = actual->sig;

b> no tengo ke comentar mucho lo ke kiero ke aga, pero la verdad es ke no hace
b> nadaa, tampoco da error al compilar.

Los punteros no controlados son peligrosos, y en tu programa dejabas unos cuantos fuera de control. Nunca se actualizaba el puntero primero->sig, por ejemplo, y al recorrer la lista, obtenías direcciones fuera de la estructura. Lo raro es que no pasase nada malo.

Paciencia, los punteros son algo "puñeteros", pero con la práctica se pueden dominar.

Hasta pronto.

-- 
Salvador Pozo (Administrador)
mailto:salvador en conclase.net


Más información sobre la lista de distribución Cconclase