You are on page 1of 11

PRÁCTICA 7

Introducción
El algoritmo trabaja de la siguiente forma:
• Elegir un elemento de la lista de elementos a
ordenar, al que llamaremos pivote.
• Resituar los demás elementos de la lista a cada
lado del pivote, de manera que a un lado queden
todos los menores que él, y al otro los mayores.
Los elementos iguales al pivote pueden ser
colocados tanto a su derecha como a su
izquierda, dependiendo de la implementación
deseada. En este momento, el pivote ocupa
exactamente el lugar que le corresponderá en la
lista ordenada.
• La lista queda separada en dos sublistas, una
formada por los elementos a la izquierda del
pivote, y otra por los elementos a su derecha.
• Repetir este proceso de forma recursiva para
cada sublista mientras éstas contengan más de un
elemento. Una vez terminado este proceso todos
los elementos estarán ordenados.
Como se puede suponer, la eficiencia del algoritmo
depende de la posición en la que termine el pivote
elegido.
• En el mejor caso, el pivote termina en el centro
de la lista, dividiéndola en dos sublistas de
igual tamaño. En este caso, el orden de
complejidad del algoritmo es O(n•log n). Silvi
esto esta entero bueno.

left = start. Pero principalmente depende del pivote. aunque habitualmente ocurre en listas que se encuentran ordenadas. lo que es ineficiente. • En el caso promedio. int temp. No es extraño. El peor caso dependerá de la implementación del algoritmo. Código Secuencial quick. si por ejemplo el algoritmo implementado toma como pivote siempre el primer elemento del array y el array que le pasamos está ordenado. int pivot. pues. int right. El orden de complejidad del algoritmo es entonces de O(n²). right = end. pivot = array[start]. el orden es O(n•log n).• En el peor caso. int start. .cpp // Función para dividir el array y hacer los intercambios int divide(int *array. int end) { int left. siempre va a generar a su izquierda un array vacío. el pivote termina en un extremo de la lista. que la mayoría de optimizaciones que se aplican al algoritmo se centren en la elección del pivote. o casi ordenadas.

array[start] = temp. } // Si todavía no se cruzan los indices seguimos intercambiando if (left < right) { temp = array[left]. array[right] = temp. array[right] = array[start]. ponemos el pivot en el lugar que le corresponde temp = array[right]. array[left] = array[right].// Mientras no se cruzen los índices while (left < right) { while (array[right] > pivot) { right--. } while ((left < right) && (array[left] <= pivot)) { left++. } // Función recursiva para hacer el ordenamiento . // La nueva posición del pivot return right. } } // Los índices ya se han cruzado.

h> #include <stdlib. // Ordeno la lista de los mayores quicksort(array.1).cpp" using namespace std. int start. end). .h> #include "quick. int end) { int pivot. pivot . pivot + 1. if (start < end) { pivot = divide(array. int main() { int const MAX = 100. } } Programa qs_se. start.cpp #include <iostream> #include <stdio. // Ordeno la lista de los menores quicksort(array. end). start.void quicksort(int *array.

arraySize . i++) { cout << a[i] << " ". i < arraySize. cout << "Ingresa tamano: " << endl. clock_t start_time. } cout << "Arreglo antes de ordenarse: " << endl. // Para que el rand no genere siempre los mismos números. double total_time. i++) { a[i] = rand() % MAX. start_time = clock(). clock_t final_time. cin >> arraySize. i < arraySize. for (int i = 0. int a[arraySize].1). utilizando la hora del sistema srand(time(0)). . // Para generar enteros aleatorios usamos rand() for (int i = 0. quicksort(a.int arraySize. 0. } cout << endl << endl.

final_time = clock().start_time)) / CLOCKS_PER_SEC. } . i++ ){ cout << a[i] << "-". i < arraySize. } cout << endl << endl. total_time = ((double)(final_time . total_time). cout << "Arreglo ordenado " << endl. return 0. printf("Tiempo de ejecución : %lf segundos \n". for (int i = 0.

int end) { if (start >= end) return 0. } int partition(int *data. int j) { int temp = data[i]. int start. int i. data[i] = data[j].h> #include <mpi.h> using namespace std. data[j] = temp. .Código Paralelo #include <iostream. void swap(int *data.h> #include <sys/time.

int start. while (data[high] > pivotValue && high > start) high--. } swap(data. char *argv[]) { MPI_Init(&argc. quicksort(data. end). start. } void quicksort(int *data. high).1. while (low < high) { while (data[low] <= pivotValue && low < end) low++. int low = start. if (low < high) swap(data. int pivot = partition(data. MPI_Comm_size (MPI_COMM_WORLD. &argv). . exit(0). start. pivot). &rank). int high = end . int rank.int pivotValue = data[start]. return high. end). pivot+1. int end) { if (end-start+1 < 2) return. if (argc < 2) { if (rank == 0) cout << "Usage: mpiqsort num_of_numbers" << endl. high). quicksort(data. MPI_Comm_rank (MPI_COMM_WORLD. } int main(int argc. start. &size). size. low.

gettimeofday(&start. s /= 2) { if (rank % s == 0) { . &status). for (s=size. } // Time everything after exchange of data until sorting is complete timeval start. s > 1. MPI_Status status. int localDataSize = length.} int length = atoi(argv[1]). int *data = new int[length]. MPI_COMM_WORLD. i++) MPI_Recv(data+i*length/size. 0. // Create random data srand(time(0)). 0. for (i=0. all // Big enough to hold it int i. } else { MPI_Send(data. length/size. MPI_ANY_TAG. MPI_INT. i<length/size. length/size. int pivot. // Send all of the data to processor 0 if (rank == 0) { for (i=1. i++) data[i] = rand(). i<size. MPI_INT. MPI_COMM_WORLD). // Do recursive quicksort starting at processor 0 and spreading out recursive calls to other machines int s. i. 0). end.

localDataSize = pivot.s/2. 0. } } // Perform local sort quicksort(data.000001*(end. localDataSize). &status). if (rank == 0) cout << "Elapsed time for sorting = " << (end. } else if (rank % s == s/2) { // Get data from processor rank . localDataSize).tv_usec)) << " seconds" << endl. rank + s/2. &localDataSize). 0). MPI_INT.tv_usec .tv_sec + . // How much data did we really get? MPI_Get_count(&status. rank . localDataSize . length. 0. 0. MPI_COMM_WORLD. MPI_COMM_WORLD).pivot. MPI_INT. MPI_INT. } . // Send everything after the pivot to processor rank + s/2 and keep up to the pivot MPI_Send(data+pivot. // Measure elapsed time gettimeofday(&end. MPI_Finalize().s/2 MPI_Recv(data.tv_sec start.start .pivot = partition(data. MPI_ANY_TAG.