[C con Clase] duda con lista en C

Steven Davidson srd4121 en njit.edu
Lun Feb 2 05:20:57 CET 2009


Hola Armando,

Armando B. VERA wrote:
> SOBRE ESTRUCTURAS DINÁMICAS DE DATOS "EDD"
> 
> Parte del siguiente codigo lo extraje del material EDD
> 
> de www.conclase.net
> 

Veamos el código fuente y las preguntas que planteas.

> ----------------------------------------------------------
> 
> typedef struct _nodo {
> 
> int valor;
> 
> struct _nodo *siguiente;
> 
> } tipoNodo;
> 
> typedef tipoNodo *pNodo;
> 
> typedef tipoNodo *Lista;
> 
> /* Funciones con listas: */
> 
> void Insertar(Lista *l, int v);
> 
> /* ¿aquí "Lista *l" es lo mismo que "tipoNodo **l" ? */
> 

Sí.

> void Insertar(Lista *lista, int v)
> 
> {
> 
> pNodo nuevo, anterior;
> 
> /* Crear un nodo nuevo */
> 
> nuevo = (pNodo)malloc(sizeof(tipoNodo));
> 
> nuevo->valor = v;
> 
> /* Si la lista está vacía */
> 
> if(ListaVacia(*lista) || (*lista)->valor > v) {
> 
> /* Añadimos la lista a continuación del nuevo nodo */
> 
> nuevo->siguiente = *lista;
> 
> /* Ahora, el comienzo de nuestra lista es en nuevo nodo */
> 
> *lista = nuevo;
> 
> }
> 
> else {
> 
> /* Buscar el nodo de valor menor a v */
> 
> anterior = *lista;
> 
> /* la pregunta es porque entonces aquí la asignación "anterior =*lista"
> 
> no sería posible ya que una es "tipoNodo *anterior" y la otra es
> 
> "tipoNodo **lista"
> 

Las declaraciones que comentas son correctas, pero no estamos asignando 
un puntero a otro, sino que primeramente accedemos al valor apuntado por 
'lista' y luego lo asignamos a 'anterior'. La expresión es la siguiente:

anterior = *lista;

Esto es lo mismo que hacer esto:

anterior = lista[0];

Como puedes ver, accedemos al valor apuntado por 'lista' y por tanto 
estamos asignando un valor de tipo 'tipoNodo *' a otro de 'tipoNodo *'.

> */
> 

[CORTE]

> 
>     * --------------------------------------------------------------------
>     * Estoy tratando de hacer algo parecido y no encuentro el error.
>     * Este es mi codigo
>     *
>     * --------------------------------------------------------------------
>     * /* ************************** palabra.c
>       ******************************* */
>     *
>     * /* La idea es que cada letra sea un nodo y se pueda escribir
>       cadenas (palabras) de forma dinámica, sin saber la longitud de la
>       misma. */
>     *
>     * #include <stdio.h>
>     * #include <stdlib.h>
>     *
>     *
>     * typedef struct letra{
>     * char letra;
>     * struct letra *sigLetra;
>     * } tipoLetra;
>     *
>     *
>     * typedef tipoLetra *pLetra;
>     * typedef tipoLetra *palabra;
>     *
>     *
>     * void insertarLetra(palabra *p, char l);
>     *
>     * int main() {
>     * char c;
>     * palabra pal=NULL;
>     *
>     * while((c=getchar())!='\n' || c!='\0') {

Esta condición debería basarse en && y no en ||.

>     * insertarLetra(&pal,c);
>     * }
>     *
>     * while(pal) {
>     * printf("%d",pal->letra);

Con esto, muestras el código ASCII de cada "letra". No sé si esto es lo 
que quieres hacer.

>     * pal=pal->sigLetra;

Esto no es NADA aconsejable. Recuerda que 'pal' es la "cabeza" de la 
lista dinámicamente enlazada. Esto significa que es el principal enlace 
a todos los nodos y por tanto a toda la memoria dinámicamente 
adjudicada. Sin este enlace no podemos liberar la memoria de la lista.

Deberías usar una variable auxiliar. Por ejemplo,

pLetra anterior;

for( anterior = *pal; anterior != NULL; anterior = anterior->sigLetra )
   printf( "%d", anterior->letra );

>     * }

Tienes que retornar un valor entero para 'main()'. Además, necesitas 
liberar la memoria que has ido adjudicando para la lista.

>     *
>     * }
>     *
>     * void insertarLetra(palabra *pal, char l){
>     * pLetra nueva;
>     * pLetra anterior;
>     *
>     * anterior=*pal; //aquí es la duda
>     *

Esto es correcto, pero ten presente que al principio, la lista está 
vacía. Por lo tanto, debes tener en cuenta esta condición. De lo 
contrario, puedes estar accediendo a 'NULL', que provocaría un error en 
tiempo de ejecución.

>     * nueva=(pLetra)malloc(sizeof(tipoLetra));
>     * nueva->letra=l;

Necesitas asignar un valor para 'nueva->sigLetra'. Como estás asignando 
nodos al final de la lista, necesitarás "apuntar a nada"; esto sería,

nueva->sigLetra = NULL;

>     *
>     * while(anterior->sigLetra!=NULL) {

Esto es correcto, sólo si 'anterior' no es un puntero nulo. Esto 
implicaría que la lista está inicialmente vacía. Debes implementar este 
caso particular.

>     * anterior=anterior->sigLetra;
>     * }
>     * anterior->sigLetra=nueva;
>     * }
>     *

Espero haber aclarado las dudas.

Steven





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