Borrar nodo en lista simplemente enlazada[C]

Iniciado por NOB2014, 24 Julio 2016, 18:33 PM

0 Miembros y 1 Visitante están viendo este tema.

NOB2014

Hola, que tengan un muy buen día. -
Tengo actualmente 2 dudas que se encuentran en las funciones menuUno y borrar. -
La primera: necesito alguna validación más o con estas cuatro es suficiente para saber si el nodo es el único y de no ser el único si es el primero o si es el último o está entre ambos. -
La restante es: si dentro de if( L->elementos == 1 )  pongo L=NULL, esto es suficiente y si la función llamadora se entera del cambio o tengo que hacer un return. -

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

struct nodo{
int dato;
struct nodo *siguiente;
};

struct lista{
struct nodo *primero;
struct nodo *ultimo;
int elementos;
};

void menu( void );
void menuUno( struct lista *L, struct nodo *N );
void limpiar( void );
struct lista *agregar( struct lista *L );
struct nodo *crear( int dato );
void mostrar( struct lista *L );
void ordenar( struct lista *L );
void buscar( struct lista *L );
void modificar( struct nodo *pivote );
void borrar( struct lista *L, struct nodo *pivote );


int main( void ){
menu();

return 0;
}


void menu( void ){
struct lista *Lista = NULL;
int opc, ok, ch;

do{
do{
limpiar();
printf( "\n ========== Menu Principal ==========\n" );
if( Lista != NULL)
printf( "\n Total de datos.....:%d\n", Lista->elementos );
printf(" \n 1 - Agregar\n 2 - buscar\n 3 - Ordenar " );
printf(" \n 4 - Total\n 5 - Finalizar\n\n Ingrese Opcion....: "  );
ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 5;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

switch ( opc ){
case 1: Lista = agregar( Lista );
break;
case 2: buscar( Lista );
break;
case 3: ordenar( Lista );
break;
case 4: mostrar( Lista );
break;
case 5:;
free(Lista);
break;
}
}while( opc != 5 );
}

void menuUno( struct lista *L, struct nodo *N ){
int opc, ok, ch;

do{
do{
limpiar();
printf( "\n ========== Menu ==========\n" );
printf(" \n 1 - Modificar\n 2 - Borrar\n 3 - Salir"
   " \n\n Ingrese Opcion....: " );
ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 5;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

switch ( opc ){
case 1: modificar( N );
opc=3;
break;
case 2: borrar( L, N );
opc=3;
break;
case 3:
break;
}
}while( opc != 3 );
}

void limpiar( void ){
system("cls||clear");
}

struct lista *agregar( struct lista *L ){
int ok, ch, dto;

do{
limpiar();
printf( "\n Ingrese dato (mayor a 0 y menor a %d)....: ", INT_MAX );
ok = scanf( "%d", &dto ) == 1 && dto >0 && dto <= INT_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

if( L != NULL ){
struct nodo *e = crear( dto );
L->ultimo->siguiente = e;
L->ultimo = e;
L->elementos++;
return L;
}else{
struct nodo *e = crear( dto );
struct lista *l = calloc( sizeof( struct lista ), 1 );
l->primero = e;
l->ultimo = e;
l->elementos = 1;
return l;
}
}

struct nodo *crear( int dato ){
struct nodo *e = calloc( sizeof( struct nodo), 1 );
e->dato = dato;
e->siguiente = NULL;

return e;
}

void mostrar( struct lista *L ){
struct nodo *auxiliar;
int i=0;

if( L != NULL ){
auxiliar = L->primero;
while( auxiliar != NULL ){
printf( "\n %d", auxiliar->dato );
auxiliar = auxiliar->siguiente;
i++;
}
}else{
printf( "\n La lista esta vacia..." );
}

printf( "\n Pulse una tecla para continuar..." );getchar();
}

void ordenar( struct lista *L ){
struct nodo *pivote = NULL, *actual = NULL;
int tmp;

if( L != NULL ){
pivote = L->primero;
while( pivote != L->ultimo ){
actual = pivote->siguiente;
while( actual != NULL ){
if( pivote->dato > actual->dato ){
tmp = pivote->dato;
pivote->dato = actual->dato;
actual->dato = tmp;
}
actual = actual->siguiente;
}
pivote = pivote->siguiente;
}
mostrar( L );
}else{
printf( "\n La lista esta vacia..." );
printf( "\n Pulse una tecla para continuar..." );getchar();
}
}

void buscar( struct lista *L ){
int ok, ch, dto, i=0;
struct nodo *pivote = NULL;

if( L != NULL ){
do{
limpiar();
printf( "\n Ingrese el dato a buscar....: " );
ok = scanf( "%d", &dto ) == 1 && dto >0 && dto <= INT_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

pivote = L->primero;
while( pivote != NULL ){
if( pivote->dato == dto  ){
menuUno( L, pivote );
i++;
break;
}
pivote = pivote->siguiente;
}
if( i == 0 ){
printf( "\n El dato no existe..." );
printf( "\n Pulse una tecla para continuar..." );getchar();
}
}else{
printf( "\n La lista esta vacia..." );
printf( "\n Pulse una tecla para continuar..." );getchar();
}
}

void modificar( struct nodo *pivote ){
int ok, ch, dto;

do{
limpiar();
printf( "\n Dato a modificar.....: %d \n Ingrese nuevo dato...: ", pivote->dato );
ok = scanf( "%d", &dto ) == 1 && dto >0 && dto <= INT_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );
pivote->dato = dto;
}

void borrar( struct lista *L, struct nodo *pivote ){

if( L->elementos == 1 ){
printf( "\n Es el unico dato..." );
}
else if( pivote == L->primero){
printf( "\n Es el primer dato..." );
}
else if( pivote->siguiente == NULL){
printf( "\n Es el ultimo dato..." );
}
else{
printf( "\n Esta entre el primer dato y el ultimo..." );
}
getchar();
}


Es todo por el momento, es probable que me surgen algunas otras dudas. -
Saludos.
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

ivancea96

En primer lugar lo segundo: Si pones en la función L = NULL, no cambiará nada fuera de la función.
De todos modos, borrar el último nodo no significa "borrar la lista". Simplemente sería borrar el nodo que tiene, y ponerlo todo a 0: elementos, primero y ultimo.
E incluso si quisieras borrar la lista, tendrías que liberar la memoria con free().

Y con respecto a lo primero, no hay mucho que decir. Si quieres que esa función borre, impleméntalo. Ya en el camino verías qué comprobaciones necesitas hacer.
Desde luego, si no es el único, estará de primero, último u otra posición, está claro.

NOB2014

Hola.
ivancea96 mucha gracia por ocuparte, con respecto a lo primero era para confirmar que estaba en lo cierto, no te olvides que estoy aprendiendo y necesitaba saber si las validaciones eran lo suficiente para hacer que el programa diera resultados correctos. -
Bueno ahora tengo inconvenientes desde la línea 230 a la 239, ¿alguien me podría dar una mano con esto? . -
El programa no me da ningún error, pero el resultado es incorrecto. -
Si el ingreso es 1 3 5 y trato de borrar el último nodo me da como resultado 1 3 0. -
El programa lo pongo completo porque tuve que efectuar algunas modificaciones. -


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

struct nodo{
int dato;
struct nodo *siguiente;
};

struct lista{
struct nodo *primero;
struct nodo *ultimo;
int elementos;
};

void menu( void );
struct lista *menuUno( struct lista *L, struct nodo *N );
void limpiar( void );
struct lista *agregar( struct lista *L );
struct nodo *crear( int dato );
void mostrar( struct lista *L );
void ordenar( struct lista *L );
struct lista *buscar( struct lista *L );
void modificar( struct nodo *pivote );
struct lista *borrar( struct lista *L, struct nodo *borrar );


int main( void ){
menu();

return 0;
}


void menu( void ){
struct lista *Lista = NULL;
int opc, ok, ch;

do{
do{
limpiar();
printf( "\n ========== Menu Principal ==========\n" );
if( Lista != NULL)
printf( "\n Total de datos.....:%d\n", Lista->elementos );
printf(" \n 1 - Agregar\n 2 - buscar\n 3 - Ordenar " );
printf(" \n 4 - Total\n 5 - Finalizar\n\n Ingrese Opcion....: "  );
ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 5;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

switch ( opc ){
case 1: Lista = agregar( Lista );
break;
case 2: Lista = buscar( Lista );
break;
case 3: ordenar( Lista );
break;
case 4: mostrar( Lista );
break;
case 5:;
free(Lista);
break;
}
}while( opc != 5 );
}

struct lista *menuUno( struct lista *L, struct nodo *N ){
int opc, ok, ch;

do{
do{
limpiar();
printf( "\n ========== Menu ==========\n" );
printf(" \n 1 - Modificar\n 2 - Borrar\n 3 - Salir"
   " \n\n Ingrese Opcion....: " );
ok = scanf( "%d", &opc ) == 1 && opc > 0 && opc <= 5;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

switch ( opc ){
case 1: modificar( N );
opc=3;
break;
case 2: L = borrar( L, N );
opc=3;
break;
case 3:
break;
}
}while( opc != 3 );

return L;
}

void limpiar( void ){
system("cls||clear");
}

struct lista *agregar( struct lista *L ){
int ok, ch, dto;

do{
limpiar();
printf( "\n Ingrese dato (mayor a 0 y menor a %d)....: ", INT_MAX );
ok = scanf( "%d", &dto ) == 1 && dto >0 && dto <= INT_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

if( L != NULL ){
struct nodo *e = crear( dto );
L->ultimo->siguiente = e;
L->ultimo = e;
L->elementos++;
return L;
}else{
struct nodo *e = crear( dto );
struct lista *l = calloc( sizeof( struct lista ), 1 );
l->primero = e;
l->ultimo = e;
l->elementos = 1;
return l;
}
}

struct nodo *crear( int dato ){
struct nodo *e = calloc( sizeof( struct nodo), 1 );
e->dato = dato;
e->siguiente = NULL;

return e;
}

void mostrar( struct lista *L ){
struct nodo *auxiliar;
int i=0;

if( L != NULL ){
auxiliar = L->primero;
while( auxiliar != NULL ){
printf( "\n %d", auxiliar->dato );
auxiliar = auxiliar->siguiente;
i++;
}
}else{
printf( "\n La lista esta vacia..." );
}

printf( "\n Pulse una tecla para continuar..." );getchar();
}

void ordenar( struct lista *L ){
struct nodo *pivote = NULL, *actual = NULL;
int tmp;

if( L != NULL ){
pivote = L->primero;
while( pivote != L->ultimo ){
actual = pivote->siguiente;
while( actual != NULL ){
if( pivote->dato > actual->dato ){
tmp = pivote->dato;
pivote->dato = actual->dato;
actual->dato = tmp;
}
actual = actual->siguiente;
}
pivote = pivote->siguiente;
}
mostrar( L );
}else{
printf( "\n La lista esta vacia..." );
printf( "\n Pulse una tecla para continuar..." );getchar();
}
}

struct lista *buscar( struct lista *L ){
int ok, ch, dto, i=0;
struct nodo *pivote = NULL;

if( L != NULL ){
do{
limpiar();
printf( "\n Ingrese el dato a buscar....: " );
ok = scanf( "%d", &dto ) == 1 && dto >0 && dto <= INT_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );

pivote = L->primero;
while( pivote != NULL ){
if( pivote->dato == dto  ){
L = menuUno( L, pivote );
i++;
break;
}
pivote = pivote->siguiente;
}
if( i == 0 ){
printf( "\n El dato no existe..." );
printf( "\n Pulse una tecla para continuar..." );getchar();
}
}else{
printf( "\n La lista esta vacia..." );
printf( "\n Pulse una tecla para continuar..." );getchar();
}
return L;
}

void modificar( struct nodo *pivote ){
int ok, ch, dto;

do{
limpiar();
printf( "\n Dato a modificar.....: %d \n Ingrese nuevo dato...: ", pivote->dato );
ok = scanf( "%d", &dto ) == 1 && dto >0 && dto <= INT_MAX;
while ((ch = getchar()) != EOF && ch != '\n');
}while( !ok );
pivote->dato = dto;
}

struct lista *borrar( struct lista *L, struct nodo *borrar ){

if( L->elementos == 1 ){
L = NULL;
}
else if( borrar == L->primero){
L->primero = borrar->siguiente;
L->elementos--;
free( borrar );
}
else if( borrar->siguiente == NULL){
struct nodo *aux = L->primero;
while( aux->siguiente != NULL ){
aux = aux->siguiente;
}
L->ultimo = aux;
L->elementos--;
aux->siguiente = NULL;
free( aux );
}
else{
printf( "\n Esta entre el primer dato y el ultimo..." );
}
return L;
}


Saludos y desde ya muchas gracias. -
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

AlbertoBSD

Hola

if( borrar->siguiente == NULL){ //Supongo que aqui estas evaluanfo por el ultimo Nodo
//a esta altura el nodo a borrar es el ultimo
struct nodo *aux = L->primero;
while( aux->siguiente != borrar ){
aux = aux->siguiente;
        }
//a esta altura el nodo aux es el penultimo
L->ultimo = aux; //El que antes era penultimo ahora sera el ultimo
L->elementos--;
aux->siguiente = NULL; //El apuntador siguiente del ultimo Nodo debe de apuntar a NULL
free( borrar );
}
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

NOB2014

#4
Hola, que tengan un muy buen día. -
Alberto, muchas gracias funcionan a la perfección, me queda un consuelo que no estaba tan errado, solo me queda ahora lidiar con que el nodo a borrar no sea ni el primero ni el último. -

Un abrazo.

==================== EDITO ====================
Bueno al fin lo logre, por lo menos para mí no da ningún error, dejo la función borrar completa por si alguien la quiere consultar o corregir. -

struct lista *borrar( struct lista *L, struct nodo *borrar ){

if( L->elementos == 1 ){ //LSE001
L = NULL;
free( borrar );
}
else if( L->primero == borrar ){ //LSE002
L->primero = borrar->siguiente; //LSE003
L->elementos--;
free( borrar );
}
else if( borrar->siguiente == NULL){ //LSE004
struct nodo *aux = L->primero;

while( aux->siguiente != borrar ){
aux = aux->siguiente;
}
//LSE005
L->ultimo = aux; //LSE006
L->elementos--;
aux->siguiente = NULL; //LSE007
free( borrar );
}
else{ //LSE008
struct nodo *aux = L->primero;

while( aux->siguiente != borrar ){ //LSE009
aux = aux->siguiente;
}
aux->siguiente = borrar->siguiente; //LSE010
L->elementos--; //LSE011
free( borrar ); //LSE012
}
return L;
}

/*
=============================== Ayuda ===============================

LSE001 Verificamos si la cantidad de ingresos es un solo dato, de ser así con L = NULL
inicializamos toda la lista a cero, pero permanece en memoria para nuevos ingresos.

LSE002 En caso de no ser el único ingreso verificamos si es el primer Nodo,   
LSE003 De ser así igualamos el primer Nodo a borrar->siguiente, de esa manera el que
era el segundo pasa a ser el primero Nodo y el primero es borrado. 

LSE004 A esta altura el nodo a borrar es el último.
LSE005 A esta altura el nodo aux es el penultimo.
LSE006 El que antes era penúltimo ahora será el último.
LSE007 El apuntador siguiente del último Nodo debe de apuntar a NULL.

LSE008 Por último, llegamos a este else porque el Nodo a borrar no es el único
ni es el primero ni es el último, se encuentra entre estos dos.

LSE009 Con este bucle obtenemos la dirección de memoria donde está el nodo anterior
al que queremos borrar.
LSE010 aux->siguiente ahora ya no apunta al Nodo siguiente que es el que queremos borrar
apunta al Nodo siguiente al que borraremos.
LSE011 Decrementamos el contador de nodos.
LSE012 Liberamos memoria.
*/ 
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-