Foros del Web » Programación para mayores de 30 ;) » C/C++ »

lista enlazada simple en C

Estas en el tema de lista enlazada simple en C en el foro de C/C++ en Foros del Web. hola como les va? me gustaria ordenar una lista enlazada simple hasta ahora lo que me salio es encontrar el nodo con el que tenga ...
  #1 (permalink)  
Antiguo 05/12/2013, 22:54
 
Fecha de Ingreso: septiembre-2010
Mensajes: 101
Antigüedad: 13 años, 7 meses
Puntos: 0
lista enlazada simple en C

hola como les va?
me gustaria ordenar una lista enlazada simple
hasta ahora lo que me salio

es encontrar el nodo con el que tenga el menor valor

como para empezar a pasarlo a otra lista nueva.

pero no se me ocurre como hacer para que vuelva a recorrer la lista a exepcion del menor que encontre

les muestro mi funcion

como siempre aclaro que solo vengo por sugerencias y opiniones de gente con mas experiencia , para aprender :)

Código C:
Ver original
  1. void ordenarMenorAmayor(punteroNodo * cabeza )
  2. {
  3.     int i = 0;
  4.     int resti =1;
  5.     int valoraux = 0;
  6.     punteroNodo menor;
  7.     punteroNodo aux;
  8.     punteroNodo nueva;
  9.     punteroNodo sustitu = *cabeza;
  10.     nueva = NULL;
  11.  
  12.    
  13.  
  14.    
  15.     menor = *cabeza;
  16.     aux = (*cabeza)->siguiente;
  17.     for(i = 0 ; i < cant-resti ; i ++)
  18.     {
  19.        
  20.         if((*cabeza)->valor > aux->valor)
  21.         {
  22.             menor = aux;
  23.         }
  24.         *cabeza = (*cabeza)->siguiente;
  25.         aux = (*cabeza)->siguiente;
  26.        
  27.     }
  28.  
  29.  
  30.     menor->siguiente = nueva;
  31.     *nueva = *menor;
  32.  
  33.     printf("menor es %d \n" , nueva->valor);
  34. }
  #2 (permalink)  
Antiguo 06/12/2013, 06:03
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: lista enlazada simple en C

Supongo que la cosa viene del mismo sitio http://www.forosdelweb.com/f96/como-...crear-1081767/

Tienes que hacer un ciclo externo para todos los elementos, y para cada vuelta haces otro ciclo interno para colisionar todos los elementos contra un numero de elementos igual a la cantidad total menos el indice del ciclo externo, que traducido sería algo así:

Código C:
Ver original
  1. int q, w, st, sz = list_length;
  2.  
  3. //ciclo externo
  4. for(q = 0; q < sz; q++) {
  5.  
  6.         //calculas las steps del ciclo interno
  7.         st = sz - q - 1;
  8.  
  9.         //ciclo interno
  10.         for(w = 0; w < st; w++) {
  11.             //algoritmo de comparacion y reordenacion
  12.         }
  13. }

Ahora la comparacion, que sería como la parte artistica: comparas como quieres; si quieres de mayor a menor o si quieres de menor a mayor, el funcionamiento es el mismo; el elemento critico siempre se mueve a la siguiente posicion de forma que en el siguiente step es el primero de los dos a comparar, y al final queda ordenado y por eso en el siguiente ciclo interno se omite ok?

Una nota: al determinar las steps siempre obtienes como maximo un numero menor a la longitud de la lista, por eso es seguro acceder a las posiciones actual y siguiente; una vez tienes localizadas las posiciones que quieres ordenar solo tienes que compararlas:

Código C:
Ver original
  1. if(cabeza[w] < cabeza[w+1]) {
  2.     //reordenacion
  3. }

Ten en cuenta que el w+1 es una operacion de riesgo, en este caso funciona porque la operacion que determina las steps me limita como ultimo indice a la longitud de la lista menos 1. Si el contador de steps estuviese mal, el w+1 podria apuntar fuera de la lista a una posicion de memoria no accesible por la aplicacion (violacion de segmento).

Ahora la comparacion , en este caso el algoritmo de comparacion es muy simple porque el < te da la solucion. Si quieres ordenar al reves (de mayor a menor) solo has de cambiar el operador. Pero si por ejemplo quisieras ordenar una lista de palabras segun el numero de caracteres primero contarias los caracteres y luego los compararias con el operador, es decir que al final haces lo mismo: determinar si hay swap o no. Puedes implementar la version extendida que consiste en llamar a una funcion externa para que te haga la comparacion y retorne un indicador de si tiene que reordenar, que sería lo que hacen las funciones de 'sort': les envias una lista y un puntero a una funcion de comparacion que defines tu, luego en base al resultado de la funcion se intercambian los elementos. Un ejemplo para hacerlo con funciones:

Código C:
Ver original
  1. //declaras las funciones de comparacion
  2. char asc(int a, int b) {
  3.     return (a > b)? 1:0;
  4. }
  5. //declaro las dos para darle mas emocion
  6. char desc(int a, int b) {
  7.     return (a < b)? 1:0;
  8. }
  9.  
  10. //declaras la funcion de ordenacion, observa el puntero a la funcion
  11. void ordenar(punteroNodo *cabeza, int (*fptr)(int , int )) {
  12.     //aqui van los ciclos
  13.     //hasta que llegas a la comparacion de cada elemento, en vez de hacerlo de forma
  14.     //directa con if(cabeza[w] < cabeza[w+1]), lo haces evaluando el retorno de la funcion
  15.     if(fptr(cabeza[w], cabeza[w+1])) {
  16.         //reordenacion
  17.     }
  18. }
  19.  
  20. //en la llamada a la funcion de ordenacion envias un puntero a la lista y otro
  21. //a la funcion que quieres usar
  22. ordenar(&lista, desc);
  23. ordenar(&lista, asc);

Esto solo es para determinar si requiere swap (intercambio); esto de las funciones auxiliares sirve para cuando tienes fechas, texto o simplemente quieres optimizar la funcion de comparacion: en vez de hacer varias funciones enteras de comparacion haces una que llame a un tipo de comparacion. Los tipos de datos de las funciones auxiliares de comparacion pueden cambiarse a punteros void* para que el tipo de dato sea cualquiera; en este caso del ejemplo se limita a enteros para que veas de que va la cosa.

Hasta aqui ok no? :)) Esto de antes de las funciones de comparacion auxiliares puedes omitirlo, pero ahora que lo conoces podras tenerlo en cuenta en otra ocasion.

Y finalmente el swap: en caso que se cumpla la condicion critica intercambias los elementos; para eso (tal como te comenté en el otro hilo) debes guardar una referencia del primer elemento que sobreescribes, asignas el segundo al primero y asignas la referencia guardada al primero:

Código C:
Ver original
  1. aux = cabeza[w];//referencia
  2. cabeza[w] = cabeza[w+1];
  3. cabeza[w+1] = aux;

Otra observacion: cuando estas trabajando con punteros sobre el original en una lista dinamica la operacion cabeza[w] = cabeza[w+1] produce una perdida de memoria (memory leak), para evitarla usas el auxiliar.

Y ya lo tienes. El lenguaje C es bonito y divertido, y si te salen las cosas aun lo es mas ;)

Saludos
vosk
  #3 (permalink)  
Antiguo 06/12/2013, 06:14
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: lista enlazada simple en C

He olvidado una cosa, en la comparacion he puesto cabeza[w] < cabeza[w+1], supongo que ya te habrás imaginado que queria decir cabeza[w]->valor < cabeza[w+1]->valor, pero no se porque lo he omitido. En el ejemplo de las funciones de comparacion auxiliares tambien va lo mismo.

Saludos
vosk

Última edición por vosk; 06/12/2013 a las 06:30
  #4 (permalink)  
Antiguo 06/12/2013, 11:27
 
Fecha de Ingreso: septiembre-2010
Mensajes: 101
Antigüedad: 13 años, 7 meses
Puntos: 0
Respuesta: lista enlazada simple en C

te agradesco mucho!!

Etiquetas: enlazada, funcion, int, lista, simple
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 16:52.