Sei sulla pagina 1di 11

Metodo Burbuja En C++

Este método consiste en comparar pares de elementos adyacentes e intercambiarlos entre


si hasta que todos se encuentren ordenados Se realizan (n-1) pasadas, transportando en
cada de las mismas el menor o mayor elemento (según sea el caso) a su posición ideal.

Codigo en c++
El Programa esta elaborado para ordenar 5 números ingresados por teclado, si su
requerimiento es ordenar más números o menos solo cambie la longitud del vector es decir
será así:

int vector[ ingrese la cantidad de números a ordenar];


..............................................................
En los 4 for que existen en este programa también realize el cambio respectivo, ingresando,
la cantidad de números a ordenar.
for(i=0;i<cantidad de números a ordenar++)
.................................................................

Nota: 1. Realice los cambios solo en las letras de color rojo.

Nota2. Este programa también le ofrece la facilidad de ordenar ascendentemente como


descendentemente, el programa que se presenta ordena en forma ascendente y si su deseo
es ordenar descendentemente solo tiene que cambiar el signo de menor(<) por el de mayor
(>). En esta parte del programa.

if(vector[j] < vector[i]) -> Forma ascendente.

if(vector[j] > vector[i]) -> Forma Descendente.

Método de ordenación Merge Sort


El algoritmo de ordenamiento por mezcla (merge sort) es un algoritmo de ordenamiento
externo estable basado en la técnica divide y vencerás. Es de Complejidad O(nlog n).

Una técnica muy poderosa para el diseño de algoritmos es "Dividir para conquistar". Los
algoritmos de este tipo se caracterizan por estar diseñados siguiendo estrictamente las
siguientes fases:
Dividir: Se divide el problema en partes más pequeñas.
Conquistar: Se resuelven recursivamente los problemas más chicos.
Combinar: Los problemas mas chicos de combinan para resolver el grande.
Los algoritmos que utilizan este principio son en la mayoría de los casos netamente
recursivos como es el caso de mergesort.
El algoritmo de Mergesort es un ejemplo clásico de algoritmo que utiliza el principio de
dividir para conquistar. Si el vector tiene más de dos elementos se lo divide en dos
mitades, se invoca recursivamente al algoritmo y luego se hace una intercalación de las
dos mitades ordenadas.

Ejemplo en c++:

// En el código usamos la clase vector (#include <vector.h>) para crear los vectores,
// obviamente funciona igual de bien si se utilizan los arrays tipo C: TIPO V[]
template <class T, class U>
void fusiona(vector<T>& v, U ini, U med, U fin) {
vector<T> aux(fin - ini + 1);
int i = ini; // Índice de la parte izquierda
int j = med + 1; // Índice de la parte derecha
int k = 0; // Índice del vector aux

/* Mientras ninguno de los indices llegue a su fin vamos realizando


comparaciones. El elemento más pequeño se copia al vector aux */
while (i <= med && j <= fin) {
if (v[i] < v[j]) {
aux[k] = v[i];
i++;
}
else {
aux[k] = v[j];
j++;
}
k++;
}

/* Uno de los dos sub-vectores ya ha sido copiado del todo, simplemente


debemos copiar todo el sub-vector que nos falte */
while (i <= med) {
aux[k] = v[i];
i++;
k++;
}

while (j <= fin) {


aux[k] = v[j];
j++;
k++;
}

/* Copiamos los elementos ordenados de aux al vector original v */


for (int n = 0; n < aux.size(); ++n) v[ini + n] = aux[n];
}

template <class T, class U>


void merge_sort(vector<T>& v, U ini, U fin) {
/* Si ini = fin el sub-vector es de un solo elemento y, por lo tanto
ya está ordenado por definición */
if (ini < fin) {
/*Considerar que el valor de med siempre es redondeado hacia abajo.*/
int med = (ini + fin)/2;
merge_sort(v, ini, med);
merge_sort(v, med + 1, fin);
fusiona(v, ini, med, fin);
}
}

Quicksort en C++
Quicksort es un algoritmo de ordenación considerado entre los más rápidos y eficientes. Fue
diseñado en los años 60s por C. A. R. Hoare un científico en computación.

El algoritmo usa la técnica divide y vencerás que básicamente se basa en dividir un problema en
subproblemas y luego juntar las respuestas de estos subproblemas para obtener la solución al
problema central.

Me pareció una buena manera de practicar programación y C++ y hacer una explicación que permite
entender este algoritmo , bueno al menos eso intenté. Hace año y medio también publiqué unos
ejemplos de ordenación en Haskell.
Voy a explicar el funcionamiento del quicksort brevemente y después veremos su implementación
en C++.

Se tiene una array de n elementos, tomamos un valor del array como pibote(usualmente el
primero), separamos los elementos menor a este pibote a la izquierda y los mayores a la derecha,
es decir, dividimos el array en 2 subarrays.

Con estos subarrays se repite el mismo proceso de forma recursiva hasta que estos tengan más de
1 elemento. Por lo tanto la función quicksort quedaría de la siguiente manera:

// Función recursiva para hacer el ordenamiento


void quicksort(int *array, int start, int end)
{
int pivot;

if (start < end) {


pivot = divide(array, start, end);

// Ordeno la lista de los menores


quicksort(array, start, pivot - 1);

// Ordeno la lista de los mayores


quicksort(array, pivot + 1, end);
}
}
La magia está en la función dividir que es la que voy a explicar a continuación:

Empezamos creando o generando un array de n elementos, por ejemplo yo use la función rand()
de C++ para generar aleatorios del 1 al 15, mi arreglo quedó así:

array[] = {8, 1, 5, 14, 4, 15, 12, 6, 2, 11, 10, 7, 9};

left right

0 1 2 3 4 5 6 7 8 9 10 11 12

8 1 5 14 4 15 12 6 2 11 10 7 9

Tomamos como pibote el 8 y usamos 2 índices que me indiquen la posición del array:

Uno que vaya de izquierda a derecha buscando los elementos mayores al pibote. array[left]
Y un índice que busque de derecha a izquierda los elementos menores al pibote. array[right]
El índice izquierdo irá aumentando en 1 mientras el array en la posición izquierda sea menor o
igual al pibote:

while ((left < right) && (array[left] <= pivot)) {


left++;
}
El índice derecho irá reduciéndose en 1 mientras el array en la posición derecha sea mayor al
pibote.

while (array[right] > pivot) {


right--;
}
Si al final de estas 2 operaciones, el índice izquierdo es menor al derecho se intercambian las
posiciones array[left] con array[right] usando una variable temporal:
En este caso, en la primer recorrido el índice izquierdo encuentra al 14 (mayor al pibote) y el índice
derecho al 7 (menor al pibote), y se intercambian los índices:

8 1 5 14 4 15 12 6 2 11 10 7 9

8 1 5 7 4 15 12 6 2 11 10 14 9

Segundo recorrido: El índice izquierdo encuentra al 15 (mayor al


pibote) y el índice derecho al 2 (menor al pibote), se intercambian:
8 1 5 7 4 15 12 6 2 11 10 14 9

8 1 5 7 4 2 12 6 15 11 10 14 9

Tercer recorrido: El índice izquierdo encuentra al 12 (mayor al pibote) y el índice derecho al 6


(menor al pibote), se intercambian:

8 1 5 7 4 2 12 6 15 11 10 14 9

8 1 5 7 4 2 6 12 15 11 10 14 9

Cuando los índices se juntan o se cruzan ponemos el pibote en el lugar que le corresponde en el
array:

temp = array[right];
array[right] = array[start];
array[start] = temp;
Se intercambian el 8 con el 6 y el array quedaría así:

6 1 5 7 4 2 8 12 15 11 10 14 9

Ahora la función quicksort se llamaría 2 veces recursivamente para los 2 subarray que tenemos:

quicksort(array, 0, 5) // el pibote está en la posición 6


quicksort(array, 7, 12) // el pibote está en la posición 6
Se repite el mismo proceso con este primer subarray quicksort(array, 0, 5)

El pibote es 6, se encuentra por la izquierda al 7 y por la derecha al 2. Se intercambian y como se


cruzaron los índices movemos el pibote a su lugar:

6 1 5 7 4 2

6 1 5 2 4 7

4 1 5 2 6 7

Otra vez tenemos 2 subarrays. Entonces se vuelve a llamar la función

quicksort(array, 0, 3) // la posición del pibote es 4


quicksort(array, 5, 5) // no se ejecuta nada, el inicio no es menor al
final
El mismo proceso. Se ejecutar quicksort (array, 0, 3). El pibote ahora es 4, se encuentra por el
índice izquierdo al 5 y por el derecho a 2. Se intercambian y como se juntaron los índices se
mueve el pivote a su lugar.
4 1 5 2

4 1 2 5

2 1 4 5
quicksort(array, 0, 1) // la posición del pibote es 2
quicksort(array, 3, 3) // no se ejecuta nada, el inicio no es menor al
final
Cuando se ejecuta quicksort (array, 0, 1) se intercambia los índices otra vez.

2 1

1 2

Ahora se llamaría a quicksort(array, 0, 0), se divide en 2 elementos el subarray y no hay nada


más que hacer por que solo tienen 1 elemento.

Ahora se ejecuta el mismo proceso con el segundo subarray del array original. Quicksort (a, 7, 12)

Se encuentra el 15 y el 9, se intercambian y como luego se juntan los índices, se coloca el pibote a


su lugar:

12 15 11 10 14 9

12 9 11 10 14 15

10 9 11 12 14 15

Tenemos otros 2 subarrays y se vuelve a llamar la función quicksort

quicksort(array, 7, 10) // posición del pibote es 10 y la primera 7


quicksort(array, 11, 12) // posición del pibote es 10 y la última 12
Se intercambian los índices y nos quedan otros 2 subarrays de 1 solo elemento entonces no se
ejecuta nada.

10 9 11

9 10 11

Con el anterior subarray (14, 15) se llama a quicksort(array, 11, 12).

14 15

Se divide en 2 elementos este subarray y no hay nada más que hacer por que los array que
contienen al 14 y al 15 solo tienen 1 elemento.

De manera que el árbol recursivo de ordenación queda más o menos así:


Quick Sort

Complejidad computacional del Quicksort:


En el mejor de los casos tiene un costo de O(n*log (n)). Que es cuando el pibote siempre queda al
medio del arreglo.

Quicksort Mejor caso

En el peor de los casos tiene un costo de O(n^2). Cuando el pibote siempre se inclina hacia a un
lado, es decir, genera una array de sólo 1 elemento y una segunda con el resto de elementos.
Quicksort peor caso

En el caso promedio también tiene un costo de O(n*log (n)). Se produce cuando el pibote se
inclina más hacia un lado y los 2 subarrays tienen distinto tamaño de elementos.

Quicksort caso promedio

Para calcular el tiempo de ejecución estoy usando la función clock() que determina el tiempo usado
por el procesador. En este caso defino 3 variables ini, final y total.

// Antes del quicksort:


clock_t start_time;
clock_t final_time;
double total_time;
start_time = clock();

// Después que se ejecuta el quicksort


final_time = clock();
total_time = ((double)(final_time - start_time)) / CLOCKS_PER_SEC;
He leído en varios sitios de c++ que la función clock no tiene mucha precisión. Si alguien sabe un
mejor método para calcular el tiempo de ejecución, algún comentario, sugerencia o aporte para
optimizar al algoritmo, bienvenido.

Queda pendiente para otro post calcular con exactitud tiempos de ejecución e implementar el
código del número de comparaciones e intercambios.

Bueno, aquí está la implementación del algoritmo en C++ disfrútenlo.

quicksort.cpp
// Función para dividir el array y hacer los intercambios
int divide(int *array, int start, int end) {
int left;
int right;
int pivot;
int temp;

pivot = array[start];
left = start;
right = end;

// Mientras no se cruzen los índices


while (left < right) {
while (array[right] > pivot) {
right--;
}

while ((left < right) && (array[left] <= pivot)) {


left++;
}

// Si todavía no se cruzan los indices seguimos intercambiando


if (left < right) {
temp = array[left];
array[left] = array[right];
array[right] = temp;
}
}

// Los índices ya se han cruzado, ponemos el pivot en el lugar que le


corresponde
temp = array[right];
array[right] = array[start];
array[start] = temp;

// La nueva posición del pivot


return right;
}

// Función recursiva para hacer el ordenamiento


void quicksort(int *array, int start, int end)
{
int pivot;

if (start < end) {


pivot = divide(array, start, end);

// Ordeno la lista de los menores


quicksort(array, start, pivot - 1);

// Ordeno la lista de los mayores


quicksort(array, pivot + 1, end);
}
}
main.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "quicksort.cpp"

using namespace std;


int main()
{
int const MAX = 100;
int arraySize;

clock_t start_time;
clock_t final_time;
double total_time;
start_time = clock();

cout << "Ingresa tamanyo: " << endl;


cin >> arraySize;

int a[arraySize];

// Para que el rand no genere siempre los mismos números, utilizando


la hora del sistema
srand(time(0));

// Para generar enteros aleatorios usamos rand()


for (int i = 0; i < arraySize; i++) {
a[i] = rand() % MAX;
}

cout << "Array antes de ordenarse: " << endl;


for (int i = 0; i < arraySize; i++) {
cout << a[i] << " ";
}

cout << endl << endl;

quicksort(a, 0, arraySize - 1);

final_time = clock();
total_time = ((double)(final_time - start_time)) / CLOCKS_PER_SEC;

printf("Tiempo de ejecución : %lf segundos \n", total_time);

cout << "Array ordenado " << endl;


for (int i = 0; i < arraySize; i++ ){
cout << a[i] << "-";
}

cout << endl << endl;

return 0;
}

Potrebbero piacerti anche