Ver Mensaje Individual
  #3 (permalink)  
Antiguo 18/04/2016, 01:57
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: Problemas con ordenamiento burbuja con punteros en lista simple

Dividir el programa en funciones pocas veces tiene tanto sentido como en tu caso.

Quieres manejar una lista simple... ¿por qué no crear una función para añadir elementos a la lista, una función para quitar elementos, ...? En vez de reescribir el mismo código 20 veces lo escribes solo una y, si resulta que tienes que modificarlo, todo el programa pasará a a beneficiarse del cambio.

Intuyo que Lista será algo más o menos asi:

Código C:
Ver original
  1. typedef struct _Lista
  2. {
  3.     struct _Lista* sig;
  4.     Ventas Vendedor;
  5. } Lista;

Llamar Lista a esta estructura no sería del todo correcto. Su nombre correcto sería Nodo y el de Lista quizás debería parecerse más a:

Código C:
Ver original
  1. typedef struct
  2. {
  3.   Nodo* primero;
  4.   int numElementos; // Para simplificar operaciones sobre la lista
  5. } Lista;

¿Por qué? Bueno, el cambio de Lista a Nodo parece obvio, realmente la estructura no es una lista sino que representa a un único nodo de la misma. Por otro lado, tener una estructura específica que pueda gestionar el inicio de la lista ayuda a que el programa pueda ganar mucha claridad.

Con esto, las funciones básicas de manipulación podrían quedar tal que:

Código C:
Ver original
  1. // Devuelve una lista inicializada.
  2. Lista NuevaLista()
  3. {
  4.   Lista toReturn;
  5.   toReturn.primero = 0;
  6.   toReturn.numElementos = 0;
  7.  
  8.   return toReturn;
  9. }
  10.  
  11. // Añade un nuevo nodo a la lista
  12. Nodo* NuevoNodo(Lista* lista)
  13. {
  14.   Nodo* nuevo = (Nodo*)calloc(1,sizeof(Nodo));
  15.  
  16.   if( lista->primero== 0 )
  17.     lista->primero= nuevo;
  18.   else
  19.   {
  20.     Nodo* ultimo = lista->primero;
  21.     while( ultimo->sig != 0)
  22.       ultimo = ultimo->sig;
  23.  
  24.     ultimo->sig = nuevo;
  25.   }  
  26.  
  27.   lista->numElementos++;
  28.  
  29.   return nuevo;
  30. }
  31.  
  32. // Elimina todos los nodos de la lista
  33. void LimpiarLista(Lista* lista)
  34. {
  35.   Nodo* nodo = lista->primero;
  36.  
  37.   while( nodo )
  38.   {
  39.     Nodo* temp = nodo->sig;
  40.     free(nodo);
  41.     nodo = temp;
  42.   }
  43.  
  44.   lista->primero = 0;
  45.   lista->numElementos = 0;
  46. }
  47.  
  48. // Saca un nodo, si existe, de la lista.
  49. // Nota que si la función retorna 1, nodo ya no es válido
  50. int EliminarNodo(Lista* lista, Nodo* nodo)
  51. {
  52.   int toReturn = 0;
  53.  
  54.   if( lista->primero == nodo )
  55.   {
  56.     lista->primero = nodo->sig;
  57.     toReturn = 1;
  58.   }
  59.   else
  60.   {
  61.     Nodo* anterior = lista->primero;
  62.  
  63.     while( anterior->sig && anterior->sig != nodo )
  64.       anterior = anterior->sig;
  65.  
  66.     if( anterior->sig )
  67.     {
  68.       anterior->sig = nodo->sig;
  69.       toReturn = 1;
  70.     }
  71.   }
  72.  
  73.   if( toReturn )
  74.   {
  75.     lista->numElementos--;
  76.     free(nodo);
  77.   }
  78.  
  79.   return toReturn;
  80. }

Con este catálogo la utilización de la lista se simplifica enormemente. Al catálogo actual habría que ir añadiendo otras funciones de interés en función de la naturaleza de la lista y de los requisitos de la aplicación... por ejemplo la posibilidad de ordenar la lista:

Código C++:
Ver original
  1. void OrdenarPorVentasMayor(Lista* lista)
  2. {
  3.   // Estructura auxiliar para ordenar
  4.   // El último nodo será 0 para simplificar el proceso
  5.   Nodo** nodos = (Nodo**)calloc(lista->numElementos+1,sizeof(Nodo*));
  6.  
  7.   // Se copian los nodos de la lista a nuestro arreglo
  8.   Nodo* nodo = lista->primero;
  9.   int index = 0;
  10.   while(nodo)
  11.   {
  12.     nodos[index] = nodo;
  13.     index++;
  14.     nodo = nodo->sig;
  15.   }
  16.  
  17.   // Se ordenan los nodos
  18.   for (int i = 0 ; i < lista->numElementos-1; i++)
  19.   {
  20.     for (int j = 0 ; j < lista->numElementos - i - 1; j++)
  21.     {
  22.       if ( nodos[j]->Vendedor.contadorventas < nodos[j+1]->Vendedor.contadorventas)
  23.       {
  24.         Nodo* swap  = nodos[j];
  25.         nodos[j]  = nodos[j+1];
  26.         nodos[j+1] = swap;
  27.       }
  28.     }
  29.   }
  30.  
  31.   // Se reconstruye la lista
  32.   lista->primero = nodos[0];
  33.   for( int i=0; i<lista->numElementos; i++)
  34.   {
  35.     // Como el último nodo es NULL, el último nodo real de la lista acabará apuntando a NULL automáticamente
  36.     nodos[i]->sig = nodos[i+1];
  37.   }
  38.  
  39.   free(nodos);
  40. }

Una forma muy sencilla de ordenar una lista enlazada (o doblemente enlazada) consiste en crear un vector de punteros a nodos. Se ordenan los punteros en dicho vector y, finalmente, se recorre ese vector ordenado para actualizar los enlaces entre los nodos. En el caso de una lista simple se puede crear la lista con un elemento "fantasma" al final para que el último nodo de la lista se quede apuntando siempre a null.

Y, como te ha dicho Instru, el código cuanto más sencillo, mejor.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.