ordenar lista enlazada simple

523 views
Skip to first unread message

aguml

unread,
Nov 27, 2014, 8:54:15 AM11/27/14
to cp...@googlegroups.com
Hola amigos estoy intentando ordenar una lista enlazada simple usando punteros y me tiene loco. Quiero usar el metodo de la burbuja porque la lista será pequeña.
Tengo este codigo:

/* DEFINICION DE TIPOS */
typedef struct ElementoLista
{
 
char *palabra;
 
int indice;
 
struct ElementoLista *sig;
}Elemento;

typedef struct ListaIdentificar {
   
Elemento *inicio;
   
Elemento *fin;
   
int nElementos;
}Lista;

int OrdenarLista(Lista *lista)
{
   
int i,j,k,cambiado;
   
Elemento *auxiliar,*auxiliar2, *actual,*inicio,*fin,*dir1,*dir2,*dir3,*dirAnterior;
   
int menor,mayor;

   
if ((auxiliar = (Elemento *) malloc (sizeof (Elemento))) == NULL)
     
return -1;

   
if ((auxiliar->palabra = (char *) malloc (SIZE_MAX_PALABRA * sizeof (char))) == NULL)
     
return -1;

   menor
=mayor=lista->inicio->indice;
   
for(actual=lista->inicio; actual != NULL; actual = actual->sig)
   
{
     
if(actual->indice < menor){
         inicio
= actual;
         menor
= actual->indice;
     
}
     
if(actual->indice > mayor)
     
{
         fin
= actual;
         mayor
= actual->indice;
     
}
   
}

   dirAnterior
= lista->inicio;
   
for (j=0, actual=lista->inicio; actual != NULL && j < lista->nElementos-1; actual= actual->sig, j++)
   
{
     
for (i=0, auxiliar2 = lista->inicio; i < (lista->nElementos-1-j) && auxiliar2->sig != NULL; i++, auxiliar2 = auxiliar2->sig)
     
{
         cambiado
= 0;
         
if (auxiliar2->indice >= auxiliar2->sig->indice)
         
{
            dir1
= auxiliar2;
            dir2
= auxiliar2->sig;
            dir3
= auxiliar2->sig->sig;

            auxiliar2
= dir2;
            auxiliar2
->sig = dir1;
            auxiliar2
->sig->sig = dir3;
            cambiado
= 1;
         
}
         
if(cambiado == 1)
            dirAnterior
->sig = auxiliar2;
         dirAnterior
= auxiliar2;
     
}
   
}

   lista
->inicio = inicio;
   lista
->fin = fin;
   actual
= lista->inicio;

   
for (actual = lista->inicio; actual != NULL; actual = actual->sig)
   
{
      printf
("%d -> %s\n",actual->indice, actual->palabra);
   
}

   system
("PAUSE");
   free
(auxiliar->palabra);
   free
(auxiliar);
   
return 0;
}

Me funciona todo bien (insercion, impresion, eliminacion,...) pero la ordenacion me tiene ya loco. A ver si podeis ayudarme por favor.

dgutson .

unread,
Nov 27, 2014, 9:05:26 AM11/27/14
to cppba
Antes que alguien te ayude, te sugiero emprolijar el código.
Por empezar, es cero modularizado. Modularizá la función en funciones
más chicas (por ejemplo, necesitás un "swap").
Por otro, tanta cantidad de variables locales ya tiene muy mal olor.

Lo debuggeaste? Lo corriste con valgrind?

A SIMPLE inspección veo que "auxiliar" no sirve para nada. Traé una
versión decente para utilizar mínimo tiempo nuestro y tal vez yo mismo
te ayude. Pero antes, mostrá esfuerzo en emprolijar esto.

Daniel.
> --
> --
> ¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido
> este mesaje por error.
> En caso de duda visita "http://groups.google.com/group/cppba"
> ---
> Has recibido este mensaje porque estás suscrito al grupo "CyC++ Buenos
> Aires" de Grupos de Google.
> Para anular la suscripción a este grupo y dejar de recibir sus mensajes,
> envía un correo electrónico a cppba+un...@googlegroups.com.
> Para acceder a más opciones, visita https://groups.google.com/d/optout.



--
Who’s got the sweetest disposition?
One guess, that’s who?
Who’d never, ever start an argument?
Who never shows a bit of temperament?
Who's never wrong but always right?
Who'd never dream of starting a fight?
Who get stuck with all the bad luck?

aguml

unread,
Nov 27, 2014, 9:34:37 AM11/27/14
to cp...@googlegroups.com
Perdon por mi ignorancia pero no se que es emprolijar.
Variables puede haber algunas que ni sirven porque de tanto probar alguna se me haya quedado descolgada.
Modularlo la verdad es que ni pensé en ello porque creia seria algo mas sencillo y se ha ido complicando mucho.
Voy a intentar modularlo y si me entero de que es emprolijar tambien intentaré resolver eso y quitar variables inservibles.

dgutson .

unread,
Nov 27, 2014, 9:36:06 AM11/27/14
to cppba
(usás un traductor? cuál es tu idioma nativo?)

Emprolijar (no sé si existe en castellano) -> hacer algo más prolijo.

Pasalo en limpio.
No más de un loop por función. Separar en "niveles", identificar las primitivas.

RFOG

unread,
Nov 27, 2014, 10:38:32 AM11/27/14
to cp...@googlegroups.com
Emprolijar como tal no existe en castellano aunque es de esas palabras que se pueden decir sin mayor problema.

Respecto a responder a la pregunta, Gutson es el master aquí. Así que hazle caso.

Enviado desde mi iPhone
> Para obtener más opciones, visita https://groups.google.com/d/optout.

aguml

unread,
Nov 27, 2014, 1:59:06 PM11/27/14
to cp...@googlegroups.com
Bueno, lo he conseguido solucionar y he hecho todo lo posible para "dividir y vencer" dividiendo las funciones en partes que se encargan de algo concreto y, como digo, lo hice correr correctamente.
La solucion que di a la funcion Swap no me ha gustado pero es que no he sido capaz de solucionarlo de otro modo. Si alguien me ayuda a hacerlo intercambiando elementos de la lista enlazada lo cambiaré ya que creo que seria mejor solucion. Aqui el codigo final del proyecto completo:

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

#define SIZE_MAX_PALABRA 30
#define SIZE_MAX_ALFABETO 27
//-----------------------------------------------------------------------------

/* DEFINICION DE TIPOS */
typedef struct ElementoLista
{
 
char *palabra;
 
int indice;
 
struct ElementoLista *sig;
}Elemento;

typedef struct ListaIdentificar {
   
Elemento *inicio;
   
Elemento *fin;
   
int nElementos;
}Lista;
//-----------------------------------------------------------------------------

/* PROTOTIPOS DE FUNCIONES */
void Inicializacion (Lista *lista);
int InsertarEnLista (Lista *lista, Elemento * actual, char *palabra, int indice);
int Sup_inicio (Lista *lista);
void DestruirLista (Lista *lista);
void Imprimir (Lista *lista);
void PreguntarPalabras(Lista *lista, int nPalabras);
int Menu(void);
void Jugar(void);
void Swap(Elemento *primero, Elemento *segundo);
void OrdenarLista(Lista *lista);
void LimpiarCadena(char *cadena, int size);
void PasarAMayusculas(char *cadena, int size);
void ActualizarLetrasIntroducidas(char *cadena, int size, char caracter);
int ActualizarLetrasRestantes(char *cadena, int size, char caracter);
int ActualizarMascara(char *mascara, char *palabra, int size, char caracter);
int LlenarLista(FILE *archivo, Lista *lista);
//-----------------------------------------------------------------------------

int main()
{
   
int retval;

   
do{
      retval
= Menu();

     
switch(retval)
     
{
         
case 1:
           
Jugar();
           
break;
     
}
   
}while(retval != 0);

   
return(0);
}
//-----------------------------------------------------------------------------

void Inicializacion (Lista *lista)
{
   lista
->inicio=NULL;
   lista
->fin=NULL;
   lista
->nElementos=0;
}
//-----------------------------------------------------------------------------

/*inserción en la lista */
int InsertarEnLista (Lista *lista, Elemento *actual, char *palabra, int indice)
{
   
Elemento *nuevo_elemento;

   
if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL)
     
return -1;

   
if ((nuevo_elemento->palabra = (char *) malloc (SIZE_MAX_PALABRA * sizeof (char))) == NULL)
     
return -1;

   strcpy
(nuevo_elemento->palabra, palabra);
   nuevo_elemento
->indice = indice;

   
if(actual != NULL)
      actual
->sig = nuevo_elemento;
   nuevo_elemento
->sig = NULL;

   
if(lista->inicio == NULL)
      lista
->inicio = nuevo_elemento;
   lista
->fin = nuevo_elemento;
   lista
->nElementos++;
   
return 0;
}
//-----------------------------------------------------------------------------

/* eliminación al inicio de la lista */
int Sup_inicio (Lista *lista)
{
   
Elemento *sup_elemento;

   
if (lista->nElementos == 0)
     
return -1;
   sup_elemento
= lista->inicio;
   lista
->inicio = lista->inicio->sig;

   
if (lista->nElementos == 1)
      lista
->fin = NULL;
   free
(sup_elemento->palabra);
   free
(sup_elemento);
   lista
->nElementos--;
   
return 0;
}
//-----------------------------------------------------------------------------

/* destruir la lista */
void DestruirLista (Lista *lista)
{
   
while (lista->nElementos > 0)
     
Sup_inicio (lista);
}
//-----------------------------------------------------------------------------

/* visualización de la lista */
void Imprimir (Lista *lista)
{
   
Elemento *actual;

   actual
= lista->inicio;
   
while (actual != NULL){
      printf
("%s\n", actual->palabra);
      actual
= actual->sig;
   
}
}
//-----------------------------------------------------------------------------

void LimpiarCadena(char *cadena, int size)
{
   
int indice;

   
for(indice = 0; indice < size; cadena[indice++] = '\0');
}
//-----------------------------------------------------------------------------

void PasarAMayusculas(char *cadena, int size)
{
   
int indice;

   
for(indice=0; indice < size;indice++)
   
{
     
if(cadena[indice] >= 'a' && cadena[indice] <= 'z')
         cadena
[indice] -= 32;
   
}
}
//-----------------------------------------------------------------------------

int ActualizarLetrasRestantes(char *cadena, int size, char caracter)
{
   
int indice, j;
   
char *aux;

   
if ((aux = (char *) malloc ((size) * sizeof (char))) == NULL)
     
return -1;

   
//Buscamos el caracter introducido en el array con los caracteres restantes
   
//Si lo encuentra lo omite y si es otro lo copia a un array auxiliar
   
for(indice=0,j=0; indice < size;indice++)
   
{
     
if(cadena[indice] != caracter)
     
{
         aux
[j]=cadena[indice];
         j
++;
     
}
   
}

   
//Si se encontró j será menor que indice con lo que finalizo la cadena auxiliar y
   
//copio el contenido de la variable auxiliar a la cadena a mostrar con los
   
//caracteres restantes
   
if(j < indice)
   
{
      aux
[j] = '\0';
      strcpy
(cadena, aux);
   
}
   free
(aux);

   
return 0;
}
//-----------------------------------------------------------------------------

void ActualizarLetrasIntroducidas(char *cadena, int size, char caracter)
{
   
int indice;

   
//Recorro los caracteres introducidos en busca del nuevo caracter
   
for(indice=0; indice < size; indice++)
     
if(cadena[indice] == caracter){
         
break;
     
}

   
//Si se ha introducido un nuevo caracter y no está en la lista
   
//le añado el nuevo caracter
   
if(size == indice)
      cadena
[size] = caracter;
}
//-----------------------------------------------------------------------------

int ActualizarMascara(char *mascara, char *palabra, int size, char caracter)
{
   
int indice, aciertos=0, encontrada=0;

   
for(indice=0; indice < size && size != 0; indice++)
     
if(mascara[indice] == caracter)
         encontrada
++;

   
if(encontrada > 0){
      aciertos
=0;
   
}else{
     
//Busco el caracter introducido en la palabra y si se encuentra lo quito de la palabra
     
for(indice=0; indice < size && size != 0; indice++)
     
{
         
if(palabra[indice] == caracter)
         
{
            mascara
[indice] = palabra[indice];
            aciertos
++;
         
}
     
}
   
}
   
return aciertos;
}
//-----------------------------------------------------------------------------

void PreguntarPalabras(Lista *lista, int nPalabras){
   
const char letrasValidas[SIZE_MAX_ALFABETO] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   
int vidas = 5, indice, largoPalabra, largoIntroducidas, largoRestantes, aciertos;
   
int contador=0, encontrados, salir = 0;
   
char palabra[SIZE_MAX_PALABRA], auxPalabra[SIZE_MAX_PALABRA];
   
char letrasIntroducidas[SIZE_MAX_ALFABETO], letrasRestantes[SIZE_MAX_ALFABETO];
   
char caracter;
   
Elemento *actual = lista->inicio;

   
do{
     
//Limpio los 3 arrays (Se puede usar en su lugar memset)
     
LimpiarCadena(letrasRestantes,SIZE_MAX_ALFABETO);
     
LimpiarCadena(letrasIntroducidas,SIZE_MAX_ALFABETO);
     
LimpiarCadena(auxPalabra,SIZE_MAX_PALABRA);

     
//Inicializo las variables que se necesiten
      strcpy
(letrasRestantes,letrasValidas);
      strcpy
(palabra,actual->palabra);
      largoPalabra
= strlen(palabra);
      encontrados
= 0;

     
//Si hay algun caracter en minusculas en la palabra lo paso a mayusculas
     
PasarAMayusculas(palabra,largoPalabra);

     
//Muestro la mascara para que se vea cuantos caracteres tiene (Se puede hacer con memset)
     
for(indice=0; indice < largoPalabra;indice++)
     
{
         auxPalabra
[indice] = '-';
     
}

     
//Mientras no lleguemos al final de la lista y tengamos vidas seguimos
     
while (actual != NULL && vidas > 0){
         
do{ //Este bucle es para descartar todos los caracteres no permitidos
           
//Muestro la informacion
            system
("CLS");
            printf
("\n%c: %d", 3, vidas);
            printf
("\nLetras introducidas: %s",letrasIntroducidas);
            printf
("\nLetras restantes: %s",letrasRestantes);
            printf
("\nNumero de palabras solucionadas: %d",contador);
            printf
("\n%s\n\n",auxPalabra);
            printf
("Introduce una letra (0 para salir): ");
            fflush
(stdin); //limpio el flujo de entrada
            caracter
= getchar(); //Pido el caracter

           
//Si el caracter introducido esta en minusculas lo paso a mayusculas
           
PasarAMayusculas(&caracter,1);

         
}while((caracter < 'A' || caracter > 'Z') && caracter != '0');

         
//Si se introdujo 0 salimos del juego
         
if(caracter == '0')
         
{
            salir
=1;
            printf
("\n\nSalida forzada por el usuario.\n\n");
           
break;
         
}

         largoRestantes
= strlen(letrasRestantes);

         
ActualizarLetrasRestantes(letrasRestantes,largoRestantes, caracter);

         
//Busco el caracter introducido en la palabra y si se encuentra lo quito de la palabra
         encontrados
+= aciertos = ActualizarMascara(auxPalabra, palabra, largoPalabra, caracter);

         
//Si se ha encontrado el caracter le resto el numero de caracteres encontrados
         
//al largo de la palabra e inicializo la variable de encontrados
         
//Si no se encuentra resto una vida
         
if(aciertos == 0){
            vidas
--;
         
}

         largoIntroducidas
= strlen(letrasIntroducidas);

         
ActualizarLetrasIntroducidas(letrasIntroducidas,largoIntroducidas, caracter);

         
//Si el largo de la palabra es 0 es porque ya se metieron todos
         
//los caracteres de dicha palabra asi que la muestro y obtengo
         
//la siguiente palabra
         
if(largoPalabra == encontrados){
            contador
++;
            system
("CLS");
            printf
("\n%c: %d", 3, vidas);
            printf
("\nLetras introducidas: %s",letrasIntroducidas);
            printf
("\nLetras restantes: %s",letrasRestantes);
            printf
("\nNumero de palabras solucionadas: %d",contador);
            printf
("\n\n%s    Solucionada!!!\n\n", palabra);
            actual
= actual->sig;
            system
("PAUSE");
           
break;
         
}

         
//Si no hay vidas hemos perdido asi que lo indico y salimos
         
if(vidas == 0)
         
{
            salir
= 1;
            system
("CLS");
            printf
("\n%c: %d", 3, vidas);
            printf
("\nLetras introducidas: %s",letrasIntroducidas);
            printf
("\nLetras restantes: %s",letrasRestantes);
            printf
("\nNumero de palabras solucionadas: %d",contador);
            printf
("\n\nPartida finalizada.\n\n");
         
}
     
}

     
//Si son iguales es porque ya solucionamos todas las palabras
     
//solicitadas asi que hemos ganado
     
if(nPalabras == contador)
     
{
         printf
("\n\nHas ganado.\n\n");
         salir
= 1;
     
}
   
}while(salir != 1);
}
//-----------------------------------------------------------------------------
//Intercambia el contenido de dos elementos de la lista
void Swap(Elemento *primero, Elemento *segundo)
{
   
char auxPalabra[SIZE_MAX_PALABRA];
   
int auxIndice;

   strcpy
(auxPalabra, primero->palabra);
   strcpy
(primero->palabra, segundo->palabra);
   strcpy
(segundo->palabra, auxPalabra);

   auxIndice
= primero->indice;
   primero
->indice = segundo->indice;
   segundo
->indice = auxIndice;
}
//-----------------------------------------------------------------------------

//Ordena el contenido de la lista
void OrdenarLista(Lista *lista)
{
   
int i,j;
   
Elemento *auxiliar, *actual;


   
for (j=0, actual=lista->inicio; actual != NULL && j < lista->nElementos-1; actual= actual->sig, j++)
   
{

     
for (i=0, auxiliar = lista->inicio; i < (lista->nElementos-1-j) && auxiliar->sig != NULL; i++, auxiliar = auxiliar->sig)
     
{
         
if (auxiliar->indice >= auxiliar->sig->indice)
         
{
           
Swap(auxiliar,auxiliar->sig);
         
}
     
}
   
}
}
//-----------------------------------------------------------------------------

int LlenarLista(FILE *archivo, Lista *lista)
{
   
int finLectura=0,j,indice,contador;
   
char caracter,palabra[SIZE_MAX_PALABRA];

   contador
= 0;
   j
=0;

   
while( finLectura != 1)
   
{
     
LimpiarCadena(palabra, SIZE_MAX_PALABRA);

     
while (!feof(archivo)){
         
do{
            caracter
=fgetc(archivo);
         
}while(caracter=='\n');

         
if (caracter!=';'){
            palabra
[j]=caracter;
            j
++;
         
}else{
            j
=0;

           
//FGETC NO SIRVE YA QUE SOLO CAPTURA UN CARACTER
           
//¿Y SI EL NUMERO ES POR EJEMPLO 10, O 150, O CUALQUIER OTRO QUE TENGA UN 1 DELANTE?
            fscanf
(archivo,"%d",&indice);

           
if(InsertarEnLista(lista,lista->fin, palabra, indice) == -1){
               printf
("\nError al insertar un elemento a la lista. Pulsa intro para salir.\n\n");
               system
("PAUSE");
               
return -1;
           
}
            contador
++;

           
LimpiarCadena(palabra,SIZE_MAX_PALABRA);
         
}
     
}
      finLectura
++;
   
}
   
return contador;
}
//-----------------------------------------------------------------------------

//Version ordenando la lista despues de haberla obtenido entera desordenada
void Jugar(){
   
int cantidad,error,contador;
   
char caracter;
   
Lista *lista;
   FILE
*archivo;
   
   
if ((lista = (Lista *) malloc (sizeof (Lista))) != NULL){
     
Inicializacion(lista);
     
do{
         system
("color b");
         system
("cls");
         printf
("\n\t\t\t  ¿Con cuantas palabras desea jugar? ");
         scanf
("%d",&cantidad);
         
if(cantidad < 3 || cantidad > 10){
            error
= 1;
            printf
("\nTiene que ser un valor comprendido entre 3 y 10\n");
            system
("PAUSE");
         
}else{
            error
= 0;
         
}
     
}while(error==1);

      archivo
= fopen("prueba.txt","r");

     
if (archivo== NULL){
         printf
("El archivo no se encuentra");
     
}else{
         
//Lleno la lista con todas las palabras del archivo indicado
         contador
= LlenarLista(archivo, lista);

         fclose
(archivo);

         
//Si se obtuvieron el numero de palabras indicadas...
         
if(contador >= cantidad)
         
{
           
OrdenarLista(lista);
           
PreguntarPalabras(lista, cantidad);
            system
("PAUSE");
            system
("CLS");

           
//Imprimimos la lista de palabras
            printf
("\nLista de palabras:");
            printf
("\n-----------------\n\n");
           
Imprimir(lista);
         
}else{
            printf
("\nHay menos palabras en el archivo que las deseadas\n\n");
         
}
     
}
     
DestruirLista(lista);
      free
(lista);
   
}
   printf
("\n");
   system
("PAUSE");
}
//-----------------------------------------------------------------------------

/*
//Version obteniendo la lista ya ordenada
void Jugar(){
   int cantidad,i,j,aux,indice,error,contador;
   char caracter,palabra[SIZE_MAX_PALABRA];
   Lista *lista;
   FILE *archivo;
   int finLecturaOrdenada=0;
   
   if ((lista = (Lista *) malloc (sizeof (Lista))) != NULL){
      Inicializacion(lista);
      do{
         system ("color b");
         system("cls");
         printf("\n\t\t\t  ¿Con cuantas palabras desea jugar? ");
         scanf("%d",&cantidad);
         if(cantidad < 3 || cantidad > 10){
            error = 1;
            printf("\nTiene que ser un valor comprendido entre 3 y 10\n");
            system("PAUSE");
         }else{
            error = 0;
         }
      }while(error==1);

      archivo= fopen("prueba.txt","r");
      if (archivo== NULL)
      {
         printf("El archivo no se encuentra");
      }else{
         contador = 1;
         i=1,j=0;
         while( finLecturaOrdenada != 2)
         {
            for(indice = 0; indice < SIZE_MAX_PALABRA; palabra[indice++] = '\0');

            while (!feof(archivo)){
               do{
                  caracter=fgetc(archivo);
               }while(caracter=='\n');

               if (caracter!=';'){
                  palabra[j]=caracter;
                  j++;
               }else{
                  j=0;

                  //FGETC NO SIRVE YA QUE SOLO CAPTURA UN CARACTER
                  //¿Y SI EL NUMERO ES POR EJEMPLO 10, O 150, O CUALQUIER OTRO QUE TENGA UN 1 DELANTE?
                  fscanf(archivo,"%d",&aux);
                  if (aux==i){
                     if(InsertarEnLista(lista,lista->fin,palabra,aux) == -1){
                        printf("\nError al insertar un elemento a la lista. Pulsa intro para salir.\n\n");
                        system("PAUSE");
                        return;
                     }
                     finLecturaOrdenada = 0;
                     fseek(archivo,0,0); //SI ENCUENTRO EL VALOR DESEADO DE INDICE ME POSICIONO AL PRINCIPIO PARA BUSCAR EL SIGUIENTE
                     contador++;
                     break;
                  }

                  for(indice = 0; indice < SIZE_MAX_PALABRA; palabra[indice++] = '\0');
               }
            }
            finLecturaOrdenada++;
            i++; //incrementamos el indice para obtener los registros ordenados

            if(i>contador){
               printf("\nHay menos palabras en el archivo que las deseadas\n\n");
               break;
            }
         }
         fclose(archivo);

         //Si se obtuvieron el numero de palabras indicadas...
         if(contador > cantidad)
         {
            PreguntarPalabras(lista, cantidad);

            system("CLS");

            //Imprimimos la lista de palabras
            printf("\nLista de palabras:\n"
                "---------------\n\n");
            Imprimir(lista);
         }
      }
      DestruirLista(lista);
      free(lista);
   }
   printf("\n");
   system("PAUSE");
}
//-----------------------------------------------------------------------------
*/


int Menu()
{
   
char resp;

   system
("color b");
   system
("cls");
   printf
("\n\n\t\t\t* * * * * MENU DE OPCIONES * * * * *");
   printf
("\n\t\t---------------------------------------------------");
   printf
("\n\t\t\t  Juego de el ahorcado ");
   printf
("\n\t\t---------------------------------------------------\n\n\n\n");
   printf
("\t\t\t\t (1) Jugar \n");
   printf
("\t\t\t\t (0) salir\n\n");
   printf
("\t\t\t\t Opcion: ");

   resp
=getchar();

   
return (resp - 48); //Devuelvo su valor entero
}
//-----------------------------------------------------------------------------





El jueves, 27 de noviembre de 2014 14:54:15 UTC+1, aguml escribió:

dgutson .

unread,
Nov 27, 2014, 4:49:04 PM11/27/14
to cppba
Algunas preguntas:

1) si tenés un "SIZE_MAX_PALABRA", entonces por qué ElementoLista
en vez de "char* palabra" no es "char palabra[SIZE_...]" ?
2) por qué swap no usa como auxiliar un ElementoLista en vez de
tener todos los campos sueltos?
3) por qué iterás mezclando un índice (comparando contra
"lista->nElementos-1-j") en vez de utilizar punteros a elementos, con
lo cual sabiendo cuál es el último? Una lista no se debe iterar "por
índice" como si fuera un array.

aguml

unread,
Nov 28, 2014, 3:55:46 AM11/28/14
to cp...@googlegroups.com
1- Tienes razon, se me pasó.
2- Eso no se como hacerlo, estuve intentandolo y no fui capaz de conseguirlo.
3- No llego a entenderlo de forma clara lo que me explicas. Es cierto que tengo el numero de elementos pero me llevé todo el dia liado con eso y no vi el modo de hacerlo.
Soy autodidacta, no tengo ningun profesor que me ayude y me explique las cosas y voy aprendiendo conforme encuentro ejercicios por internet (la mayoria sin solucion) e intento solucionarlos por mi cuenta y si no puedo pues busco ayuda. Las listas las he podido ver en escritos de internet donde explican y ponen ejemplos pero el tema de la ordenacion no vi nada. Si vi que hay mas gente con la misma pregunta y alguno le contesta que utilice una lista auxiliar pero es que no veo la manera por muchas vueltas que le de. La unica manera que se me ocurre con una lista auxiliar es recorrer toda la lista en busca del menor, una vez tengo el menor lo añado a la auxiliar y lo elimino de la otra y asi hasta que nElementos sea 0. Luego libero la memoria de la lista y hago que el puntero de esta apunte a la direccion de auxiliar. Una locura la verdad. ¿Me puedes ayudar?

aguml

unread,
Nov 28, 2014, 4:17:31 AM11/28/14
to cp...@googlegroups.com
me he ayudado de este escrito: http://es.kioskea.net/faq/2842-la-lista-enlazada-simple
La verdad que tiene algunas erratas en el codigo pero las explicaciones y los esquemas me han ayudado mucho ya que no me enteraba de nada.

Nicolás Brailovsky

unread,
Nov 28, 2014, 7:49:11 AM11/28/14
to cp...@googlegroups.com
Para preguntas no puntuales, herramientas como refactormycode.com son muy utiles ;)


Nicolás Brailovsky


2014-11-28 10:17 GMT+01:00 aguml <ag...@hotmail.com>:
me he ayudado de este escrito: http://es.kioskea.net/faq/2842-la-lista-enlazada-simple
La verdad que tiene algunas erratas en el codigo pero las explicaciones y los esquemas me han ayudado mucho ya que no me enteraba de nada.
--
--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
---
Has recibido este mensaje porque estás suscrito al grupo "CyC++ Buenos Aires" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+un...@googlegroups.com.
Para obtener más opciones, visita https://groups.google.com/d/optout.

aguml

unread,
Nov 28, 2014, 8:50:08 AM11/28/14
to cp...@googlegroups.com
no me deja entrar, dice que está en mantenimiento ¿Para que sirve?

aguml

unread,
Dec 1, 2014, 6:18:03 AM12/1/14
to cp...@googlegroups.com
He conseguido hacerlo usando una lista auxiliar y funciona perfecto pero no se hasta que punto sería correcto hacerlo así y si es exactamente lo que me indicabas tu. Pongo la nueva funcion de ordenación y sus dependencias:

void Inicializacion (Lista *lista)
{
   lista
->inicio=NULL;
   lista
->fin=NULL;
   lista
->nElementos=0;
}
//-----------------------------------------------------------------------------

/*inserción en la lista */
int InsertarEnLista (Lista *lista, Elemento *actual, char *palabra, int indice)
{
   
Elemento *nuevo_elemento;


   
if ((nuevo_elemento = (Elemento *) malloc (sizeof (Elemento))) == NULL)
     
return -1;

   
if ((nuevo_elemento->palabra = (char *) malloc (SIZE_MAX_PALABRA * sizeof (char))) == NULL)
     
return -1;

   strcpy
(nuevo_elemento->palabra, palabra);

   nuevo_elemento
->indice = indice;

   
if(actual != NULL)
      actual
->sig = nuevo_elemento;
   nuevo_elemento
->sig = NULL;

   
if(lista->inicio == NULL)
      lista
->inicio = nuevo_elemento;
   lista
->fin = nuevo_elemento;
   lista
->nElementos++;
   
return 0;
}
//-----------------------------------------------------------------------------

/* eliminar un elemento después de la posición solicitada */
int Sup_en_lista (Lista * lista, int pos)
{
   
int i;
   
Elemento *actual;
   
Elemento *sup_elemento;

   
if (lista->nElementos <= 1 || pos < 1 || pos >= lista->nElementos)
     
return -1;

   actual
= lista->inicio;
   
for (i = 1; i < pos; ++i)
      actual
= actual->sig;
   sup_elemento
= actual->sig;
   actual
->sig = actual->sig->sig;
   
if(actual->sig == NULL)
      lista
->fin = actual;

   free
(sup_elemento->palabra);
   free
(sup_elemento);
   lista
->nElementos--;
   
return 0;
}
//-----------------------------------------------------------------------------

/* eliminación al inicio de la lista */
int Sup_inicio (Lista *lista)
{
   
Elemento *sup_elemento;

   
if (lista->nElementos == 0)
     
return -1;
   sup_elemento
= lista->inicio;
   lista
->inicio = lista->inicio->sig;

   
if (lista->nElementos == 1)
      lista
->fin = NULL;
   free
(sup_elemento->palabra);
   free
(sup_elemento);
   lista
->nElementos--;
   
return 0;
}
//-----------------------------------------------------------------------------

/* destruir la lista */
void DestruirLista (Lista *lista)
{
   
while (lista->nElementos > 0)
     
Sup_inicio (lista);
}
//-----------------------------------------------------------------------------

//Ordena el contenido de la lista
int OrdenarLista(Lista *lista)
{
   
int j,pos,retval;
   
Elemento *actual,*menor;
   
Lista *listaAux;

   
if(lista->nElementos > 1){
     
//Reservo memoria para la lista auxiliar que usaré para ordenar la lista
     
if ((listaAux = (Lista *) malloc (sizeof (Lista))) == NULL){
         retval
= -1; //Valor de retorno que indica que no se pudo obtener suficiente memoria
     
}else{
         
//Inicializo la lista auxiliar
         
Inicializacion(listaAux);

         
//Mientras que el número de elementos sea mayor que 1...
         
while(lista->nElementos > 1){
            menor
= lista->inicio; //le asigno al puntero de tipo Elemento la direccion de inicio de la lista
            pos
=0; //inicializo la variable para saber la posicion del elemento anterior al de menor indice

           
//Recorro todos los elementos en busca del que tenga menor indice
           
for (j=1, actual=lista->inicio; j < lista->nElementos; j++, actual=actual->sig)
           
{
               
//Si el indice del actual es mayor que el del siguiente...
               
if(menor->indice > actual->sig->indice){
                  menor
= actual->sig; //Asigno a menor la direccion del elemento siguiente
                  pos
= j; //Asigno a pos la posicion del elemento anterior al que tiene el indice menor
               
}
           
}
           
//Inserto el elemento menor en la lista auxiliar
           
InsertarEnLista(listaAux, listaAux->fin, menor->palabra, menor->indice);

           
if(pos==0){ //Si pos es 0 es porque es el primer elemento de la lista
               
Sup_inicio(lista); //Elimino al primer elemento de la lista
           
}else{ //Si pos es diferente de 0...
               
Sup_en_lista(lista,pos); //Elimino el elemento que está despues de la posicion pos
           
}
         
}

         
if(lista->nElementos == 1){ //Si hay un solo elemento en la lista...
           
//Inserto ese elemento en la lista auxiliar ya que es el último que falta por ordenar y el que tiene mayor indice
           
InsertarEnLista(listaAux, listaAux->fin, lista->inicio->palabra, lista->inicio->indice);
           
Sup_inicio(lista); //Elimino el elemento que queda para limpiar la lista
         
}

         
//Recorro la lista auxiliar para rellenar la lista
         
for(j=0, actual=listaAux->inicio; j < listaAux->nElementos; j++, actual=actual->sig)
           
InsertarEnLista(lista, lista->fin, actual->palabra, actual->indice);

         
DestruirLista(listaAux); //Libero la memoria de los elementos de la lista auxiliar
         free
(listaAux); //Libero la memoria de la lista auxiliar
         retval
=0; //Valor de retorno que indica que todo fue bien
     
}
   
}else{
      retval
= -2; //Valor de retorno que indica que el numero de elementos de la lista no es correcto
   
}
   
return retval;
}



El resto de funciones no las pongo aquí porque no hay variacion alguna con el codigo anterior.
Si hay otra manera mejor que esta me gustaria saber como hacerlo ¿podeis ayudarme? Ya digo que soy autodidacta y que no puedo ir a pedir ayuda a un profesor en clase ya que para mi no existe esa clase y por eso intento buscar ayuda en la red siempre que la necesito y considero que aquí hay gente muy preparada y capaz que podría ayudarme y aclarar mis dudas siempre y cuando ellos lo deseen y consideren oportuno jejeje.

Hugo Arregui

unread,
Dec 1, 2014, 6:48:41 AM12/1/14
to cp...@googlegroups.com
Hola,

On 01/12/14, aguml wrote:
>He conseguido hacerlo usando una lista auxiliar y funciona perfecto pero no
>se hasta que punto sería correcto hacerlo así y si es exactamente lo que me
>indicabas tu.

En gral. se podría decir que lo que estas haciendo no es correcto.
Crear una lista auxiliar es ineficiente en muchas formas: tanto en
memoria (por que tenes q duplicar la cantidad de elementos), como en
velocidad, pues tenes que iterar varias veces (para construir y
reconstruir).

Yo continuaría con la versión anterior, me parece que lo que te había
quedado por resolver era avanzar por punteros en lugar de por indice
no?. Es muy simple, supongamos que tenes un puntero q en ppio apunta
al primer elemento:

Elemento ptr = lista->inicio;

ese ptr será el que vaya desplazándose por la lista, o sea que el
siguiente elemento es simplemente:

ptr = ptr->sig;

si? Te das cuenta como seguir? Hasta cuando tenes que seguir avanzado?

Una cosa más: es bueno agregar comentarios al código, pero fíjate que
a veces es simplemente redundante, te dejo algunos ejemplos del ultimo
código que mandaste:

>/*inserción en la lista */
>int InsertarEnLista (Lista *lista, Elemento *actual, char *palabra, int
>indice)

>/* destruir la lista */
>void DestruirLista (Lista *lista)

>//Ordena el contenido de la lista
>int OrdenarLista(Lista *lista)

>//Inicializo la lista auxiliar
>Inicializacion(listaAux);

>//Mientras que el número de elementos sea mayor que 1...
>while(lista->nElementos > 1){

etc.

Se entiende lo que quiero decir no? El comentario no agrega nada que
no sea obvio, y es desgastante leerlo. La idea sería que el código
hable por si mismo, y en los lugares donde esto no es posible, hagas
una aclaración.

Saludos,
Hugo

dgutson .

unread,
Dec 1, 2014, 7:13:56 AM12/1/14
to cppba

Coincido con todo lo que dijo Hugo. Más aún, te aconsejo sacar "nElementos" de la lista así haces todo con punteros.

Pd: Hugo, no te tenía escribiendo en ANSI Spanish ;-)

--
--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error. En caso de duda visita "http://groups.google.com/group/cppba"
--- Has recibido este mensaje porque estás suscrito al grupo "CyC++ Buenos Aires" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+unsubscribe@googlegroups.com.

Jorge Atala

unread,
Dec 1, 2014, 7:59:08 AM12/1/14
to cppba
debe tener hasta el editor del mail con las 80 columnas marcadas ;)

Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+un...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

aguml

unread,
Dec 1, 2014, 9:22:47 AM12/1/14
to cp...@googlegroups.com
amigos con puntero lo intenté de todas las maneras y el problema era el siguiente:
Tenia un puntero de tipo elemento como auxiliar para poder intercambiar.
Luego iba por la lista usando el metodo de la burbuja intercambiando los punteros.
Si intercambiaba los punteros luego necesitaba intercambiar los valores de sig para que no se rompiera la lista.
Y al menor lo ponia como inicio de la lista y al mayor como final de la lista.

Esa era la idea pero no fui capaz de conseguirlo ya que solo ordenaba algunos y la lista se rompia.

Hugo Arregui

unread,
Dec 1, 2014, 9:35:19 AM12/1/14
to cp...@googlegroups.com
On 01/12/14, aguml wrote:
>amigos con puntero lo intenté de todas las maneras y el problema era el siguiente:
>Tenia un puntero de tipo elemento como auxiliar para poder intercambiar.
>Luego iba por la lista usando el metodo de la burbuja intercambiando los punteros.
>Si intercambiaba los punteros luego necesitaba intercambiar los valores de sig para que no se rompiera la lista.
>Y al menor lo ponia como inicio de la lista y al mayor como final de la lista.

Me parece que hablamos de cosas distintas, ya llegaremos a eso. Lo que
estamos diciendo es que la iteración (solo eso), funcione por punteros
y no por indices. O sea que cada elemento ya no contendría su posición
en la lista. Solo el contenido y el puntero al siguiente.

>Pd: Hugo, no te tenía escribiendo en ANSI Spanish ;-)

Jajaja.

On 01/12/14, Jorge Atala wrote:
>debe tener hasta el editor del mail con las 80 columnas marcadas ;)

autocmd FileType mail setl textwidth=70
autocmd FileType mail setl fo+=aw

;-)

aguml

unread,
Dec 1, 2014, 10:42:21 AM12/1/14
to cp...@googlegroups.com
Esto es lo que hice con punteros:

Elemento * ObtenerMayor(Lista *lista)
{
   
Elemento *actual, *fin;
   fin
=lista->fin;

   
for(actual = lista->inicio; actual != NULL; actual=actual->sig){
     
if(actual->indice > fin->indice)
         fin
= actual;
   
}
   
return fin;

}
//-----------------------------------------------------------------------------

//Intercambia el contenido de dos elementos de la lista
Elemento * Swap(Lista *lista, Elemento *primero, Elemento *segundo)
{
   
Elemento *aux, *sigAux;

   aux
= primero;
   sigAux
= segundo->sig;
   primero
= segundo;
   segundo
= aux;
   segundo
->sig = sigAux;
   primero
->sig = segundo;
   
return primero;
}
//-----------------------------------------------------------------------------


//Ordena el contenido de la lista
void OrdenarLista(Lista *lista)
{
   
Elemento *auxiliar, *actual, *menor, *mayor;

   menor
= ObtenerMenor(lista);
   mayor
= ObtenerMayor(lista);

   
for (actual=lista->inicio; actual != NULL; actual= actual->sig)
   
{
     
for (auxiliar = lista->inicio; auxiliar->sig != NULL; auxiliar = auxiliar->sig)

     
{
         
if (auxiliar->indice >= auxiliar->sig->indice)
         
{

            auxiliar
= Swap(lista,auxiliar,auxiliar->sig);
         
}
     
}
   
}
   lista
->inicio = menor;
   lista
->fin = mayor;
}

Los elementos de la lista son estos:
abuela;9
hola
;2
adios
;4
aqui
;3
alli
;5
mama
;1
papa
;7
hijo
;6
abuelo
;8



Algo hago mal y no se que es ya que doy la primera pasada y el primer elemento me lo ordena perfecto, o sea, el que tiene indice 9 lo pone en ultimo lugar y con lo que ahora "abuela"->sig apunta a NULL y el problema lo tengo al intentar obtener el segundo elemento de la lista ya que seria NULL, no se si me explico. Ahi es donde estoy atascado.


El jueves, 27 de noviembre de 2014 14:54:15 UTC+1, aguml escribió:

Jorge Atala

unread,
Dec 1, 2014, 10:56:03 AM12/1/14
to cppba
revisa swap, no hace lo que vos crees, empeza pensando que estas modificando auxilares y no punteros de la lista, ademas pensa: el nodo anterior a primero, a quien queda apuntando? Tenes un lio de punteros, te recomiendo dibujar en papel los nodos y poner flechitas de punteros, te vas a dar cuenta enseguida.

Despues de arreglar el swap, seguimos con esos 2 bucles de OrdenarLista, pero primer arregla el swap

--

Hugo Arregui

unread,
Dec 1, 2014, 10:58:44 AM12/1/14
to cp...@googlegroups.com
On 01/12/14, aguml wrote:
>Esto es lo que hice con punteros:

La iteración con punteros esta perfecta. Pero yo te entendí mal o
querías usar bubble sort?

Fíjate el pseudo código en wikipedia (o donde te quede más cómodo):

https://es.wikipedia.org/wiki/Ordenamiento_de_burbuja

No busques el mayor o el menor, simplemente se van comparando de a dos
e intercambiando en caso de ser necesario.

Un consejo (sentite libre de seguirlo o no): intenta preguntar acerca
de cosas que no entiendas del algoritmo, o de C, no cosas que
impliquen debug o comportamiento de tu programa. No porque no lo
podamos responder o porque ese tipo de preguntas sean censurables, el
tema es que si estas queriendo aprender, si no es algo que necesites
resolver, de nada te va a servir que te lo contestemos (sería
equivalente a buscar un bubble sort resuelto en C, lo que seguramente
podrías hacer). Incluso podes aprovechar, si tenes ganas, para conocer
un debugger (lease gdb). Es más, si queres probalo y pregunta las
dudas que te surjan, si es que algo no te cierra (cosa que
probablemente pase, porque gdb es un gusto adquirido).

Saludos,
Hugo

aguml

unread,
Dec 1, 2014, 5:56:48 PM12/1/14
to cp...@googlegroups.com
si es un bubble soft lo que quiero y lo hice planteandolo en papel y no doy con la tecla.
El menor y mayor era simplemente para, al terminar la ordenacion, actualizar el inicio y final de la lista.
Lo unico que se me ocurre es que en la swap poner dos condicionales.
El primero comprueba si el primer elemento es lista->inicio y si lo es hago que lista->inicio apunte al segundo elemento.
El segundo hago lo mismo pero con lista->fin para tener siempre bien el inicio y fin de la lista.
¿Puede ser esa la solucion? Mañana lo probaré a ver si lo consigo hacer funcionar.

Hugo Arregui

unread,
Dec 1, 2014, 7:50:28 PM12/1/14
to cp...@googlegroups.com
On 01/12/14, aguml wrote:
>si es un bubble soft lo que quiero y lo hice planteandolo en papel y no doy con la tecla.
>El menor y mayor era simplemente para, al terminar la ordenacion, actualizar el inicio y final de la lista.
>Lo unico que se me ocurre es que en la swap poner dos condicionales.
>El primero comprueba si el primer elemento es lista->inicio y si lo es hago que lista->inicio apunte al segundo elemento.

Despreocúpate por el momento de fin e inicio. Compara lo que hace
bubble sort en el pseudocódigo de wikipedia y lo que vos hiciste en
esa parte.

Cuidado con las condiciones del for, y cuidado con las variables que
usas. Podes traducir lo más literalmente posible el pseudocódigo de
wikipedia a C?

aguml

unread,
Dec 2, 2014, 6:18:25 AM12/2/14
to cp...@googlegroups.com
ok amigo, hay cosas en mi codigo que no se corresponden con el pseudocodigo que indicas y lo solucionaré en cuanto pueda usar el pc. De todos modos, si te fijas, en el segundo bucle siempre inicia desde el primer elemento y termina en n-i. Si no debo usar nElementos que corresponderia a n ¿Como hago para eso? El otro punto es, si no actualizo inicio y fin (sobre todo inicio) ¿Como sabré cual es el primero al iniciar el segundo bucle? Piensa que si el primero es mayor que el segundo, en la primera pasada el primero ya no seria el primero con lo que tendria problemas. Esas son las dos cuestiones que peor tengo.

Jorge Atala

unread,
Dec 2, 2014, 7:36:28 AM12/2/14
to cppba
Mira Agumi, paso a paso esto hace tu swap (lo cual esta bien) el problema lo tenes en que le estas asignado el puntero que retorna a un puntero auxiliar, entonces tu lista queda rota.




cuando retornas "primero" se lo tenes que asignar al "nodo anterior de la lista"->siguiente, no a "auxiliar". Se entiende?

El 2 de diciembre de 2014, 8:18, aguml <ag...@hotmail.com> escribió:
ok amigo, hay cosas en mi codigo que no se corresponden con el pseudocodigo que indicas y lo solucionaré en cuanto pueda usar el pc. De todos modos, si te fijas, en el segundo bucle siempre inicia desde el primer elemento y termina en n-i. Si no debo usar nElementos que corresponderia a n ¿Como hago para eso? El otro punto es, si no actualizo inicio y fin (sobre todo inicio) ¿Como sabré cual es el primero al iniciar el segundo bucle? Piensa que si el primero es mayor que el segundo, en la primera pasada el primero ya no seria el primero con lo que tendria problemas. Esas son las dos cuestiones que peor tengo.
--
--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
---
Has recibido este mensaje porque estás suscrito al grupo "CyC++ Buenos Aires" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+un...@googlegroups.com.
Para obtener más opciones, visita https://groups.google.com/d/optout.

aguml

unread,
Dec 3, 2014, 4:09:03 AM12/3/14
to cp...@googlegroups.com
Gracias Jorge, tu esquema me ha aclarado el problema y me ha ayudado mucho. Gracias tambien al resto por su ayuda que tambien me ha ayudado mucho a entender como hacerlo. Lo he conseguido pero usando nElementos ya que no he sido capaz de otra manera. Pongo lo que hice al final:

//Intercambia el contenido de dos elementos de la lista y nos devuelve el puntero al primero

Elemento * Swap(Lista *lista, Elemento *primero, Elemento *segundo)
{
   
Elemento *aux, *sigAux;

   aux
= primero;
   sigAux
= segundo->sig;
   primero
= segundo;
   segundo
= aux;
   segundo
->sig = sigAux;
   primero
->sig = segundo;

   
return primero;
}
//-----------------------------------------------------------------------------

//Ordena el contenido de la lista
void OrdenarLista(Lista *lista)
{

   
int i,j;
   
Elemento *actual, *anterior;

   
for (i=1; i < lista->nElementos; i++)
   
{
     
for (j=0, actual = lista->inicio, anterior = NULL; j < lista->nElementos-(i); j++, actual = actual->sig)
     
{
         
if (actual->indice >= actual->sig->indice)
         
{
           
//Si el elemento actual es el primero de la lista pongo al que apunta el puntero
           
//sig del actual como inicio ya que serán intercambiados
           
if(actual == lista->inicio)
               lista
->inicio = actual->sig;

           
//Si el puntero sig de actual es el mismo que el fin de la lista pongo al actual
           
//como fin ya que voy a intercambiarlos
           
if(actual->sig == lista->fin)
               lista
->fin = actual;

           
//Intercambio los elementos
            actual
= Swap(lista,actual,actual->sig);

           
//Si anterior es igual a NULL será porque actual es el primer elemento de la lista
           
//y por lo tanto no existe un elemento anterior
           
//Si no es NULL actualizo el puntero sig del elemento anterior al nuevo elemento
           
//actual despues del intercambio
           
if(anterior != NULL)
               anterior
->sig = actual;
         
}
         
//Guardo el puntero al elemento actual para la siguiente pasada
         anterior
= actual;
     
}
   
}
}

Por favor, si saben hacerlo mejor, diganme como sería ya que me gustaria saber hacerlo lo mejor posible y mi coco ya no da para mas XD


El jueves, 27 de noviembre de 2014 14:54:15 UTC+1, aguml escribió:

aguml

unread,
Dec 3, 2014, 4:16:42 AM12/3/14
to cp...@googlegroups.com
Me acabo de dar cuenta que ha la funcion Swap le sobra el parametro Lista asi que se lo he quitado y ha quedado asi: Elemento * Swap(Elemento *primero, Elemento *segundo);


El jueves, 27 de noviembre de 2014 14:54:15 UTC+1, aguml escribió:

Daniel Gutson

unread,
Dec 3, 2014, 5:27:38 AM12/3/14
to cp...@googlegroups.com
Como sería un for que recorra todos los elementos, pero con punteros? (No con indices ni con nElementos)
From: aguml <ag...@hotmail.com>
Date: Wed, 3 Dec 2014 01:16:42 -0800 (PST)
Subject: [cppba] Re: ordenar lista enlazada simple
--
--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
---
Has recibido este mensaje porque estás suscrito al grupo "CyC++ Buenos Aires" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+un...@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

aguml

unread,
Dec 3, 2014, 7:23:01 AM12/3/14
to cp...@googlegroups.com, daniel...@gmail.com
Creo que sería:

//Ordena el contenido de la lista
void OrdenarLista(Lista *lista)
{
   
int i,j;

   
Elemento *auxiliar, *actual, *anterior;

   
for (auxiliar=lista->inicio; auxiliar != NULL; auxiliar = auxiliar->sig)
   
{
     
for (actual = auxiliar, anterior = NULL; actual->sig != NULL; actual = actual->sig)

     
{
         
if (actual->indice >= actual->sig->indice)
         
{
           
//Si el elemento actual es el primero de la lista pongo al que apunta el puntero
           
//sig del actual como inicio ya que serán intercambiados
           
if(actual == lista->inicio)
               lista
->inicio = actual->sig;

           
//Si el puntero sig de actual es el mismo que el fin de la lista pongo al actual
           
//como fin ya que voy a intercambiarlos
           
if(actual->sig == lista->fin)
               lista
->fin = actual;

           
//Intercambio los elementos

            actual
= Swap(actual,actual->sig);


           
//Si anterior es igual a NULL será porque actual es el primer elemento de la lista
           
//y por lo tanto no existe un elemento anterior
           
//Si no es NULL actualizo el puntero sig del elemento anterior al nuevo elemento
           
//actual despues del intercambio
           
if(anterior != NULL)
               anterior
->sig = actual;
         
}
         
//Guardo el puntero al elemento actual para la siguiente pasada
         anterior
= actual;
     
}
   
}
}

Ordenar ordena pero no se si hago algo mal o deberia hacerse de otra forma.

Hugo Arregui

unread,
Dec 3, 2014, 7:39:51 AM12/3/14
to cp...@googlegroups.com, daniel...@gmail.com
Sugerencia: que te sería mas simple verlo si en lugar de auxiliar y actual
los llamas i,j como antes (solo q esta vez son punteros).

Nota: en gral llamar "auxiliar" a una variable es casi siempre
incorrecto (excepto en casos como en el swap, donde auxiliar es
justamente lo que es). A veces pienso que deberían dejar de usar el
concepto de "variable auxiliar" en clases/textos de algoritmos, porque
el lector/alumno se siente impelido a usar variables con nombres tales
como auxiliar, aux, aux1... (y con razon!) en lugar de buscar el
nombre de lo que realmente es.

Jorge Atala

unread,
Dec 3, 2014, 7:43:27 AM12/3/14
to cppba, Daniel Gutson
Agumi, si entendiste lo del swap, porque seguis asignando el retorno de la funcion a "actual" ese es un puntero auxiliar, no estas modificando realmente nada en la lista. Aparte en el primer if de tu algoritmo estas dejando fuera de la lista un nodo (el primero) y en el segundo if dejas inconsistenete el puntero lista->fin (deja de apuntar al ultimo elemento)

aguml

unread,
Dec 3, 2014, 8:27:23 AM12/3/14
to cp...@googlegroups.com
Aparte en el primer if de tu algoritmo estas dejando fuera de la lista un nodo (el primero) y en el segundo if dejas inconsistenete el puntero lista->fin (deja de apuntar al ultimo elemento)
A ver si me se explicar.
Asigno el valor de retorno a actual porque, si intercambio primero con segundo, actual sería segundo al salir de swap con lo cual me saltaría un elemento. Lo vi traceando que pasaba eso y por eso al retornar retorno el valor del primero de los 2 para que al hacer actual->sig apunte al siguiente y no a actual->sig->sig. Mo se si me explico.
Lo que indicas del primer if, pues yo no lo veo, ya que al iniciar el for asigno lista->inicio a actual y en la comparacion comparo el indice de este con el del siguiente en la primera pasada.
Lo de lista->fin, tampoco lo veo.
Al final de la funcion puse esto:

*lista->fin;
*lista->inicio;
lista
->fin=lista->fin;

y puse un bp en la ultima de las 3 y una vez para veo posicionando el puntero encima que tanto fin como inicio apuntan donde deben. ¿puedes explicar mejor lo que me indicas? porque yo no los veo esos fallos.

Con respecto a usar nombres como aux, auxiliar... es que es una tentacion ya que es un nombre facil de asignar y que vale para todo jijiji.

Con respecto a hacerlo solo con punteros, lo unico que conseguí es lo siguiente aunque ya digo que no es tan eficiente como el que hize usando indices y no se como hacerlo igual de eficiente:

//Ordena el contenido de la lista
void OrdenarLista(Lista *lista)
{
   
int i,j;

   
Elemento *auxiliar, *actual, *anterior, *siguiente;

   siguiente
= lista->inicio->sig;
   
for (auxiliar=lista->inicio; siguiente != NULL; auxiliar = siguiente, siguiente = siguiente->sig)
   
{
     
for (actual = lista->inicio, anterior = NULL; actual->sig != NULL; actual = actual->sig)

     
{
         
if (actual->indice >= actual->sig->indice)
         
{
           
//Si el elemento actual es el primero de la lista pongo al que apunta el puntero
           
//sig del actual como inicio ya que serán intercambiados
           
if(actual == lista->inicio)
               lista
->inicio = actual->sig;

           
//Si el puntero sig de actual es el mismo que el fin de la lista pongo al actual
           
//como fin ya que voy a intercambiarlos
           
if(actual->sig == lista->fin)
               lista
->fin = actual;

           
//Intercambio los elementos
            actual
= Swap(actual,actual->sig);

           
//Si anterior es igual a NULL será porque actual es el primer elemento de la lista
           
//y por lo tanto no existe un elemento anterior
           
//Si no es NULL actualizo el puntero sig del elemento anterior al nuevo elemento
           
//actual despues del intercambio
           
if(anterior != NULL)
               anterior
->sig = actual;
         
}

         
//Guardo el puntero al elemento actual para la siguiente pasada
         anterior
= actual;
     
}
   
}
}
Reply all
Reply to author
Forward
0 new messages