Anda di halaman 1dari 11

INSTITUTO POLITCNICO

NACIONAL
ESCUELA SUPERIOR DE CMPUTO
ANLISIS Y DISEO DE
ALGORITMOS PARALELOS
PRCTICA 7
PROFRA: SANDRA LUZ MORALES BUITRN

ALUMNO: DAZ BERMDEZ LUIS RICARDO

Introduccin
El algoritmo trabaja de la siguiente forma:
Elegir un elemento de la lista de elementos a
ordenar, al que llamaremos pivote.
Resituar los dems 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 implementacin
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 ms de un
elemento. Una vez terminado este proceso todos
los elementos estarn ordenados.
Como se puede suponer, la eficiencia del algoritmo
depende de la posicin en la que termine el pivote
elegido.
En el mejor caso, el pivote termina en el centro
de la lista, dividindola en dos sublistas de
igual tamao. En este caso, el orden de
complejidad del algoritmo es O(nlog n). Silvi
esto esta entero bueno.
En el peor caso, el pivote termina en un extremo
de la lista. El orden de complejidad del
algoritmo es entonces de O(n). El peor caso
depender de la implementacin del algoritmo,
aunque habitualmente ocurre en listas que se
encuentran ordenadas, o casi ordenadas. Pero
principalmente depende del pivote, si por

ejemplo el algoritmo implementado toma como


pivote siempre el primer elemento del array y el
array que le pasamos est ordenado, siempre va a
generar a su izquierda un array vaco, lo que es
ineficiente.

En el caso promedio, el orden es O(nlog n).


No es extrao, pues, que la mayora de
optimizaciones que se aplican al algoritmo se
centren en la eleccin del pivote.

Cdigo Secuencial
quick.cpp
// Funcin 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 todava 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 posicin del pivot


return right;
}

// Funcin 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);
}
}

Programa
qs_se.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "quick.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 tamano: " << endl;


cin >> arraySize;

int a[arraySize];

// Para que el rand no genere siempre los mismos nmeros,


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 << "Arreglo 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 ejecucin : %lf segundos \n",


total_time);

cout << "Arreglo ordenado " << endl;


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

cout << endl << endl;

return 0;
}

Cdigo Paralelo
#include <iostream.h>
#include <sys/time.h>
#include <mpi.h>
using namespace std;

void swap(int *data, int i, int j) {


int temp = data[i];
data[i] = data[j];
data[j] = temp;
}

int partition(int *data, int start, int end) {


if (start >= end) return 0;
int pivotValue = data[start];
int low = start;
int high = end - 1;
while (low < high) {
while (data[low] <= pivotValue && low < end) low++;
while (data[high] > pivotValue && high > start) high--;
if (low < high) swap(data, low, high);
}
swap(data, start, high);
return high;
}

void quicksort(int *data, int start, int end) {


if

(end-start+1 < 2) return;

int pivot = partition(data, start, end);


quicksort(data, start, pivot);
quicksort(data, pivot+1, end);
}

int main(int argc, char *argv[]) {


MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank (MPI_COMM_WORLD, &rank);
MPI_Comm_size (MPI_COMM_WORLD, &size);
if (argc < 2) {
if (rank == 0)
cout << "Usage: mpiqsort num_of_numbers" << endl;
exit(0);
}
int length = atoi(argv[1]);
// Create random data
srand(time(0));
int *data = new int[length];
all

// Big enough to hold it

int i;
for (i=0; i<length/size; i++)
data[i] = rand();
MPI_Status status;
// Send all of the data to processor 0
if (rank == 0) {
for (i=1; i<size; i++)

MPI_Recv(data+i*length/size, length/size, MPI_INT, i,


MPI_ANY_TAG, MPI_COMM_WORLD, &status);
}
else {
MPI_Send(data, length/size, MPI_INT, 0, 0,
MPI_COMM_WORLD);
}
// Time everything after exchange of data until sorting is
complete
timeval start, end;
gettimeofday(&start, 0);
// Do recursive quicksort starting at processor 0 and
spreading out recursive calls to other machines
int s;
int localDataSize =

length;

int pivot;
for (s=size; s > 1; s /= 2) {
if (rank % s == 0) {
pivot = partition(data, 0, localDataSize);

// Send everything after the pivot to processor rank +


s/2 and keep up to the pivot
MPI_Send(data+pivot, localDataSize - pivot, MPI_INT,
rank + s/2, 0, MPI_COMM_WORLD);
localDataSize = pivot;
}
else if (rank % s == s/2) {
// Get data from processor rank - s/2
MPI_Recv(data, length, MPI_INT, rank - s/2,
MPI_ANY_TAG, MPI_COMM_WORLD, &status);
// How much data did we really get?

MPI_Get_count(&status, MPI_INT, &localDataSize);


}
}
// Perform local sort
quicksort(data, 0, localDataSize);

// Measure elapsed time


gettimeofday(&end, 0);
if (rank == 0)
cout << "Elapsed time for sorting = " << (end.tv_sec start.tv_sec + .000001*(end.tv_usec - start
.tv_usec)) << " seconds" << endl;

MPI_Finalize();
}

Anda mungkin juga menyukai