Jump to content

Ayuda con listas enlazadas


Recommended Posts

Hola gente recurro a uds porque tengo la siguiente duda, estoy escribiendo en C un programa para crear lista enlazada, ingresar nodos en base a lo que uno decida, mostrar los nodos, eliminar alguno a eleccion y salir.

 

Codigo:

 

 

 

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

ingresa_nodo (Lista *p)
	{
		int cant, num, i;
		printf("Cuantos nodos quiere ingresar?\n");
		scanf("%d", &cant);
		for (i=1; i<=cant; ++i)
		
		{
			printf ("Ingrese nodos: \n");
			scanf("%d",&num);
			p=insertar_nodo_lista(p, num);
		}
	return (p);
	}
	
void mostrar_lista (Lista *p)
	{
		while (p !=NULL)
		{
			printf ("%d",p->info);
			p = p->prox;
		}	
	}
	
int main(int argc, char *argv[]) {
	int op;
	Lista *pl;
	pl=NULL;
	while(op!=4)
    {
        printf("\n\n_____________________________\n\n");
        printf("1.- Ingresar Nodos\n");
        printf("2.- Visualizar Contenido Lista\n");
        printf("3.- Eliminar Nodo\n");
        printf("4.- Salir\n");
        printf("_____________________________\n");
        printf("Elegir Opcion: ");
        scanf("%d", &op);

        switch(op)
        {
            case 1:
            {
            	pl=ingresa_nodo (pl);
			break;
			}
			
			case 2:
            {
           		mostrar_lista (pl);
			break;
			}
			
			case 3:
			{
				
				
			break;
			}
			
			case 4: break;
    	}
	}
	return 0;
} 

 

Consejos del codigo, ojala para eliminar nodo a eleccion, osea para poder hacer uso del auxiliar y cambiar los punteros.

 

Codigo Fuente:

 

 

 

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


//--------------------- Lista enlazada simple --------------------------

struct nodo_lista {
	int info;
	struct nodo_lista *prox;
};

#define lista struct nodo_lista
#define Lista struct nodo_lista

lista *insertar_nodo_lista (lista *p, int dato)
{
	lista *paux;

	// Inicio:
			paux = NULL;
			paux = (lista *) malloc (sizeof (lista));
			
			if (paux!=NULL)
			{
				paux->info = dato;
				paux->prox = NULL;				
			
				if (p == NULL)
					p = paux;
				else
				{
					paux->prox = p;
					p = paux;
				}
				paux = NULL;
			}
			else
				printf ("No hay memoria...\n\n");
			
			return (p);
}



// Elimina complemente una lista enlazada

lista *eliminar_lista (lista *p)
{

	lista *paux;

	// Inicio:

	while (p != NULL)
	{
		paux = p;
		p = p->prox;
		free (paux);	
	}
	paux= NULL; 

	return (p);
}


// Muestra el contenido de una lista enlazada

void listar_lista (lista *p)
{
	// Inicio:

	printf ("\n");
	while (p != NULL)
	{
		printf ("%d, ",p->info);
		p = p->prox;
	}
	printf ("\n");

}


// ------------Fin de lista enlazada -----------------------------------------//





// ------------ Lista Circular ----------------------------------------------//

lista *insertar_nodo_circular (lista *pc, int dato)
{
	lista *paux;

	// inicio:
			paux = NULL;
			paux = (lista *) malloc (sizeof (lista));
			
			if (paux!=NULL)
			{
				paux->info = dato;
				paux->prox = paux;				
			
				if (pc == NULL)
					pc = paux;
				else
				{	
					// insertar:

					paux->prox = pc->prox;
					pc->prox = paux;
				}

				paux = NULL;
			}
			else
				printf ("No hay memoria...\n\n");
			
			return (pc);
}



lista *eliminar_circular (lista *p)
{

	lista *paux;

	// Inicio:

	if (p != NULL)
	{
		paux = p;
		p = p->prox;
		paux->prox = NULL;

		p = eliminar_lista (p);
		
	}


	return (p);

}

// ------------Fin de lista circular -----------------------------------------// 

 

 

 

De antemano gracias por leer.

 

PD: Algunas funciones estan integradas en el include lista.h si es necesario puedo subirlo.

Edited by brian69
Link to comment
Share on other sites

:mmm: Hay varios problemas:

  • No subiste el código fuente de lista.h :huasonto: ...y soy terriblemente malo para adivinar
  • Las funciones que no devuelven ningún valor tienes que declararlas como void. En C, si no especificas un tipo de dato para un identificador, se asume que éste es int, o sea, implícitamente se declara como int. Así que deberías arreglar las funciones ingresa_nodo y mostrar_lista (así como están actualmente, están devolviendo un entero)
  • La función ingresa_nodo está mal implementada. Estás ingresando nodos dentro de la función, pero al salir de ésta, todo queda igual (la lista queda igual como estaba antes de entrar a la función) :otnot: . Tienes que hacer que la función devuelva la nueva lista (un puntero al comienzo de ésta) ;), o sea, sería la misma idea de la función insertar_nodo_lista (suponiendo que esté bien implementada... :nose: )
  • Se supone que la lista se inicializa en NULL (indicando que está vacía) al comienzo del programa, tú la inicializas en NULL cada vez que entras a la función ingresa_nodo, pero esto ni siquiera importa porque, como dije antes, esta función deja la lista tal cual como estaba antes de entrar a la función.
  • Como la variable pl que está en el main no está inicializada, contiene basura, o sea, apunta a cualquier parte, por eso te ocurre un error (estás tratando de acceder a una dirección de memoria a la que el programa no tiene permiso para acceder)
  • Como no subiste el codigo fuente de lista.h, no puedo estar seguro si la definición del tipo Lista es correcta :nose: y, como dije antes, soy malazo para adivinar :otnot:
Sobre el tercer punto, la función ingresa_nodo no altera la lista porque los parámetros de funciones se comportan igual que variables locales, así que da lo mismo qué le asignes al parámetro p dentro de la función porque es una variable local. Por ejemplo, podrías agregar una función que supuestamente asignaría NULL a una lista y, por lo tanto, la destruiría (haría que todos los nodos que tenga quedaran inaccesibles), la función sería así:

void anular(Lista *p)
{
p = NULL;
}
como dije, esto no funciona. La lista quedaría tal cual porque el parámetro p tiene validez dentro de la función. Por esta misma razón, en la función mostrar_lista no necesitas usar una variable auxiliar para recorrer la lista :huasonto: (haz la prueba ;) ) Edited by susodicho
  • Upvote 1
Link to comment
Share on other sites

:mmm: Hay varios problemas:

  • No subiste el código fuente de lista.h :huasonto: ...y soy terriblemente malo para adivinar
  • Las funciones que no devuelven ningún valor tienes que declararlas como void. En C, si no especificas un tipo de dato para un identificador, se asume que éste es int, o sea, implícitamente se declara como int. Así que deberías arreglar las funciones ingresa_nodo y mostrar_lista (así como están actualmente, están devolviendo un entero)
  • La función ingresa_nodo está mal implementada. Estás ingresando nodos dentro de la función, pero al salir de ésta, todo queda igual (la lista queda igual como estaba antes de entrar a la función) :otnot: . Tienes que hacer que la función devuelva la nueva lista (un puntero al comienzo de ésta) ;), o sea, sería la misma idea de la función insertar_nodo_lista (suponiendo que esté bien implementada... :nose: )
  • Se supone que la lista se inicializa en NULL (indicando que está vacía) al comienzo del programa, tú la inicializas en NULL cada vez que entras a la función ingresa_nodo, pero esto ni siquiera importa porque, como dije antes, esta función deja la lista tal cual como estaba antes de entrar a la función.
  • Como la variable pl que está en el main no está inicializada, contiene basura, o sea, apunta a cualquier parte, por eso te ocurre un error (estás tratando de acceder a una dirección de memoria a la que el programa no tiene permiso para acceder)
  • Como no subiste el codigo fuente de lista.h, no puedo estar seguro si la definición del tipo Lista es correcta :nose: y, como dije antes, soy malazo para adivinar :otnot:
Sobre el tercer punto, la función ingresa_nodo no altera la lista porque los parámetros de funciones se comportan igual que variables locales, así que da lo mismo qué le asignes al parámetro p dentro de la función porque es una variable local. Por ejemplo, podrías agregar una función que supuestamente asignaría NULL a una lista y, por lo tanto, la destruiría (haría que todos los nodos que tenga quedaran inaccesibles), la función sería así:
void anular(Lista *p)
{
    p = NULL;
}
como dije, esto no funciona. La lista quedaría tal cual porque el parámetro p tiene validez dentro de la función. Por esta misma razón, en la función mostrar_lista no necesitas usar una variable auxiliar para recorrer la lista :huasonto: (haz la prueba ;) )

 

Gracias compa, de hecho durante la tarde corregi varios errores los cuales mencionas, anoche empeze a escribirlo tipo 23hrs asi qe tampoco tava muy "concentrado" xd

 

Dejare el codigo como esta ahora y agregare el codigo fuente.

 

Me podrias ayudar con un modulo para eliminar a eleccion? en estos momento yo ingreso la cantidad de nodos, elijo 3 a ingresar, luego me muestra los nodos en este orden : "321" y por ejemplo quiero eliminar el 2, ahi creo necesario tirar un auxiliar y cambiar donde apunta.

 

Gracias por pasar, leer y aportar

Link to comment
Share on other sites

No arreglaste bien la función ingresa_nodo... :huasonto:

 

:mmm: Para eliminar un nodo, tienes que saber cuál es el nodo anterior al que vas a eliminar, para enlazarlo con el que viene después. Por ejemplo, si tienes esta lista:

A -> B -> C -> D -> E -> F -> G -> H -> I -> J
y quieres eliminar el nodo G, entonces tienes que enlazar el nodo F con el nodo H, una vez enlazados puedes eliminar el nodo G.

 

Creo que la función eliminar_nodo sería más o menos así (pseudocódigo):

Lista *eliminar_nodo(Lista *p, cual)
    anterior = NULL
    inicio = p

    while (p <> NULL) and (no es el nodo que ando buscando)
        anterior = p
        avanzar(p)

    if p = NULL then
        // ERROR: ese nodo no existe
    elseif anterior = NULL then
        // hacer que 'inicio' apunte al nodo que viene después de 'p'
        // borrar 'p'
    else
        // enlazar nodo 'anterior' con el que viene después de 'p'
        // borrar 'p'

    return inicio
end
Ojalá que se entienda. Ten cuidado de no confundir las comparaciones y asignaciones en el pseudocódigo y en el lenguaje C ;)

Al salir del while hay que verificar lo siguiente:

  • si se encontró el nodo que se quiere eliminar
  • si se va a eliminar el primer nodo
si no se encontró el nodo que se quiere eliminar entonces p será NULL (se recorrió la lista completa o estaba vacía); si anterior es NULL significa que no se entró al ciclo while y, por lo tanto, se va a eliminar el primer nodo; en caso contrario se va a eliminar algún otro nodo (del segundo en adelante).

 

Ojo, el hecho que no se encuentre el nodo que se quiere eliminar, no significa haya que tirar error o hacer algo, quizás no haya que hacer nada; eso queda a criterio tuyo (si no hay que hacer nada, tendrías que reestructurar los if...tú sabrás cómo ;) )

 

Por último, parece que no es necesario usar una variable auxiliar a la hora de borrar el nodo.

Edited by susodicho
Link to comment
Share on other sites

les dejo mi biblioteca personal de listas enlazadas simples xD

#ifndef LISTA_H_INCLUDED
#define LISTA_H_INCLUDED

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

/* Definicion de la lista. */
struct nodo{
	int n;
	struct nodo *sgte;
};

/* Prototipos */
struct nodo* crear(struct nodo* l)
void printLista(struct nodo *inicio);
int length(struct nodo *inicio);
struct nodo* insertarOrdenAscendente(struct nodo *inicio, int val);
struct nodo* insertarInicio(struct nodo *inicio, int val);
struct nodo* insertarFinal(struct nodo *inicio, int val);
struct nodo *buscarValor(struct nodo *inicio, int val);
struct nodo *delete(struct nodo *inicio, int val);


/* Crea una lista vacia */
struct nodo* crear(struct nodo* l){
	return l = NULL;
}


/* Imprime una lista desde el primer elemento */ 
void printLista(struct nodo *inicio){
	struct nodo *p;

	printf("Lista: ");
	p = inicio;
	while (p!=NULL){
		printf("%d ", p->n);
		p = p->sgte;
	}
   printf("\n");
}

int length(struct nodo *inicio){
	struct nodo *p;
	int len;

	len = 0;
	p = inicio;
	while (p!=NULL){
		len++;
		p = p->sgte;
	}

	return len;
}

/* inserta un nuevo nodo manteniendo la lista ordenada de forma ascendente */
struct nodo* insertarOrdenAscendente(struct nodo *inicio, int val){
	struct nodo *p, *new;

	new = (struct nodo*)malloc(sizeof(struct nodo));
	new->n = val;

	/* Lista vacia */
	if (inicio==NULL){
		inicio = new;
		inicio->sgte = NULL;
	}
	/* Lista con elementos */
	else{
		/* Caso especial (se debe insertar como primer elemento) */
		if (val < inicio->n){
			new->sgte = inicio;
			inicio = new;
		}
		/* Caso general */
		else{
			p = inicio;
			while (p->sgte!=NULL && (p->sgte)->n < val)
			p = p->sgte;
			new->sgte = p->sgte;
			p->sgte = new;
		}
	}

	return inicio;
}

/* inserta un nuevo nodo al inicio de la lista, desplazando el resto de los nodos */
struct nodo* insertarInicio(struct nodo *inicio, int val){
	struct nodo *new;

	new = (struct nodo*)malloc(sizeof(struct nodo));
	new->n = val;
	new->sgte = inicio;
	return new;
}

/* inserta un nuevo nodo al final de la lista */
struct nodo* insertarFinal(struct nodo *inicio, int val){
	struct nodo *p, *new;

	new = (struct nodo*)malloc(sizeof(struct nodo));
	new->n = val;
	new->sgte = NULL;

	/* Lista vacia */
	if(inicio == NULL){
		inicio = new;
	}
	else{
		p = inicio;
		while (p->sgte != NULL)
			p = p->sgte;
		p->sgte = new;
	}

   return inicio;
}

/* busca un valor en una lista, retorna el puntero al primer nodo que contenga dicho valor */
struct nodo *buscarValor(struct nodo *inicio, int val){
	struct nodo *p;

	p = inicio;
	while (p!=NULL && p->n!=val)
		p = p->sgte;
	return p;
}


/* borra un nodo de la lista liberando la memoria usada por este */
struct nodo *delete(struct nodo *inicio, int val){
	struct nodo *p, *aux;

	if(inicio != NULL){
		/* Caso especial (se debe borrar el primer nodo) */
		if (inicio->n == val){
			aux = inicio;
			inicio = aux->sgte;
			free(aux);
		}
		else{
			/* Se busca el nodo a borrar */
			p = inicio;
			while (p->sgte!=NULL && (p->sgte)->n!=val)
				p = p->sgte;

			/* se borra en nodo */
			if (p->sgte != NULL){
				aux = p->sgte;
				p->sgte = aux->sgte;
				free(aux);
			}
		}
	}

	return inicio;
}
#endif // LISTA_H_INCLUDED

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...