Mostrando entradas con la etiqueta intercambio. Mostrar todas las entradas
Mostrando entradas con la etiqueta intercambio. Mostrar todas las entradas

martes, 24 de mayo de 2016

Ordenamiento de una lista simplemente enlazada

El ordenamiento de una lista simplemente enlazada es similar al ordenamiento de vectores con la gran diferencia de que en una lista simplemente enlazada no disponemos del concepto del “índice” que nos ayuda a acceder directamente a un elemento de la lista, en este caso para acceder a un elemento debemos recorrer desde el inicio hasta hallar el elemento que nos interese.

Un algoritmo sencillo es el del Intercambio, consiste en lo siguiente:

1. Situar un puntero al inicio de la lista que nos irá indicando a medida que vayamos ordenando, cuánto de la lista ya está ordenada, es la variable más importante del algoritmo porque nos servirá para saber que hemos acabado de ordenar la lista.

Elemento * elemBase = elemInicio;
while(elemBase != NULL)
{
//en este proceso vamos ordenando la lista a partir del nodo elemBase hasta el final
elemBase = elemBase->next;
}

2. En el caso que el ordenamiento sea de menor a mayor, necesitamos encontrar el menor de los elementos a partir del elemento base hasta el final de la lista.
En el caso del ordenamiento de Vectores obteníamos la posición, en este caso obtendremos un puntero al menor elemento.

Elemento* buscarMenor(Elemento* ptrInicial)

Esta función tendría que utilizarse en cada iteración

Elemento * elemBase = elemInicio;
Elemento* elemMenor; //puntero que nos sirve para apuntar al menor elemento encontrado
while(elemBase != NULL)
{
elemMenor = buscarMenor(elemBase);
elemBase = elemBase->next;
}

3. Intercambiar el elemento menor con el elemento que se encuentra apuntando el puntero base. Para hacer este intercambio es necesario que el elemento anterior al elemento base apunte al elemento menor, para eso necesitamos un puntero que apunte al anterior del elemento base.

Como es una lista simplemente enlazada, no podemos retroceder para hallar al puntero anterior al puntero base, por tanto, crearemos una función que nos sirva para ubicarnos en el elemento anterior que queramos. Esta función es necesaria para luego poder hacer el intercambio de nodos.

Elemento * getElemAnterior(Elemento* elemInicio, Elemento* elem);

Utilizaremos esta función para obtener el elemento anterior al base y al menor y de esta forma poder realizar el intercambio

Elemento * elemAnteBase = NULL;//puntero que apunta al anterior de elemento base
Elemento * elemBase = elemInicio;
Elemento* elemAnteMenor; //puntero que apunta al anterior del elemento menor
Elemento* elemMenor; //puntero que nos sirve para apuntar al menor elemento encontrado
while(elemBase != NULL)
{
elemMenor = buscarMenor(elemBase);
elemAnteBase = getElemAnterior(elemInicio, elemBase);
elemAnteMenor = getElemAnterior(elemInicio, elemMenor);
elemBase = elemBase->next;
}

Teniendo el puntero anterior al base ya podemos hacer el intercambio:

void intercambio(Elemento* elemAnteBase, Elemento* elemBase,
Elemento* elemAnteMenor, Elemento* elemMenor);

Incorporamos el intercambio en cada iteración y asignamos el nodo menor como el nuevo elemento base:

Elemento * elemAnteBase = NULL;//puntero que apunta al anterior de elemento base
Elemento * elemBase = elemInicio;
Elemento* elemAnteMenor; //puntero que apunta al anterior del elemento menor
Elemento* elemMenor; //puntero que nos sirve para apuntar al menor elemento encontrado
while(elemBase != NULL)
{
elemMenor = buscarMenor(elemBase);
elemAnteBase = getElemAnterior(elemInicio, elemBase);
elemAnteMenor = getElemAnterior(elemInicio, elemMenor);
intercambio(elemAnteBase, elemBase, elemAnteMenor, elemMenor);
elemBase = elemMenor;
elemBase = elemBase->next;
}

4. Finalmente desarrollamos las funciones:

Elemento* buscarMenor(Elemento* ptrInicial)
{
Elemento* elemMenor = ptrInicial;
Elemento* ptr = ptrInicial;//puntero que sirve para recorrer la lista
int menorValor = elemMenor.valor;//inicializamos el primer valor menor
//recorremos toda la lista y dejamos el puntero elemMenor en el de menor valor
while(ptr!=NULL)
{
if(ptr.valor < menorValor)
{
elemMenor = ptr;
menorValor = ptr.valor;
}
ptr = ptr->next;
}
return elemMenor;
}

void intercambio(Elemento* elemAnteBase, Elemento* elemBase,
Elemento* elemAnteMenor, Elemento* elemMenor)
{
Elemento* aux = elemBase->next; //nos sirve para hacer el intercambio sin perder punteros
elemBase->next = elemMenor->next;
elemMenor->next = aux;
elemAnteBase->next = elemMenor;
elemAnteMenor->next = elemBase;
}

Elemento * getElemAnterior(Elemento* elemInicio, Elemento* elem)
{
Elemento*anterior = NULL;
Elemento*ptr = elemInicio;
int finBusqueda = 0;
while(ptr!=NULL && ptr->next!=NULL && !finBusqueda)
{
if(ptr->next.valor == elem.valor)
{
finBusqueda = 1;
}
anterior = ptr;
ptr = ptr->next;
}
return anterior;


}




miércoles, 7 de agosto de 2013

Vectores: Ordenamiento por Intercambio

En este post veremos paso a paso cómo ordenar un vector de números de 5 elementos de forma ascendente. Luego generalizaremos la solución a un vector de N elementos.

Planteamiento del Problema

¿Qué tengo?
Un vector de 5 números



¿Qué quiero?
Ordenar el vector de forma ascendente



¿Cómo lo hago?
- Tenemos 5 elementos, de los cuales iremos ordenando posición a posición (empezando por la posición 0)
- Una posición está ordenada cuando todos los elementos de las posiciones posteriores son mayores que el elemento de la posición que se está ordenando.
<imagen de posición i ordenada>
- Si ordenamos posición a posición, vemos que si ordenamos de la posición 0 a la 3, la cuarta quedará ordenada automáticamente (no hay posiciones posteriores con la cual compararla)

Siguiendo estas pautas, haremos el procedimiento para el vector de 5 elementos, razonando a cámara lenta:
(ver enlace)

Ahora que hemos visto poco a poco cómo sería la ejecución del algoritmo, planteamos el pseudocódigo para el vector de 5 elementos:

/***Método de Ordenamiento General***/
iPos = 0; //representa cada posición del vector
Para cada elemento del Vector hasta la posición 3
  OrdenarDesde(iPos); //Ordena el vector a partir de la posición iPos
Fin Para

/***Método OrdenarDesde***/
iPosCompara = iPos + 1; //esta variable es la que recorre las posiciones posteriores a iPos para comparar
elemento1 = Vector[iPos];
Mientras (iPosCompara <= 4)
   elemento2 = Vector[iPosCompara];
   //Se comparan: elemento1 y elemento2
   Si elemento1<= elemento2 //no tiene que cambiar de posición
      iPosCompara++
   Caso Contrario
      Intercambia(iPos, iPosCompara) //intercambia los elementos
      iPosCompara =  iPos + 1; //vuelve a empezar el ordenamiento desde la posición iPos
      elemento1 = Vector[iPos];
   Fin Si
Fin Mientras

/***Método Intercambia***/
aux = Vector[iPos]; //guarda temporalmente el valor de la posición iPos
Vector[iPos] = Vector[iPosCompara];
Vector[iPosCompara] = aux; //utiliza el valor guardado en aux para el intercambio

Para terminar, os dejo el mismo código como un proyecto de consola en c# generalizado para vectores de N elementos.
- Programa Principal
- Clase con Algortimo de Ordenamiento