Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Быстрая сортировка / mf
.cpp#include "stdafx.h"
#include "mf.h"
#include <iostream>
#include <conio.h>
using namespace std;
unsigned int N =0;
//////////////////////////////////////////////////////////
void sortarray(double * arr, unsigned int size)
{
if (size <= 1)
return;
int k = median(arr, size);
int l = 0, r = size - 1, flag_l = 0, flag_r = 0;
double T;
T = arr[(size-1)/2];
arr[(size-1)/2] = arr[k];
arr[k] = T;
k = (size - 1)/2;
l = 0; r = size - 1;
do
{
while (arr[l] <= arr[k] && l != k) //ищем слева от медианы значение больше медианы
{
l++;
}
while (arr[r] >= arr[k] && r != k) //ищем справа от медианы значение меньше медианы
r--;
if (l == k) flag_l = 1;
if (r == k) flag_r = 1;
T = arr[l];
arr[l] = arr[r];
arr[r] = T;
if (flag_l == 1 && flag_r != 1)
{
k = r;
flag_l = 0;
}
else if (flag_l != 1 && flag_r == 1)
{
k = l;
flag_r = 0;
}
}
while (l != r);
sortarray(&arr[0], k);
if (k < size)
sortarray(&arr[k+1], size-k-1);
}
//////////////////////////////////////////////////
DWORD WINAPI ThSort(LPVOID arguments)
{
LPRECORD arguments1 = (LPRECORD)arguments; //приводим параметр к типу указатель на структуру
if(arguments1->size = 0) //если сортируемый массив пуст
return 0; //возвращаемся
int k = median(arguments1->data, arguments1->size); //вычисляем медиану массива
int l = 0, r = arguments1->size - 1, flag_l = 0, flag_r = 0; //l - левая граница анализируемого диапазона
//r - правая
//флаги указывают, совпадают ли границы с медианой
double T; //буфер
HANDLE h; //дескриптор потока
DWORD IdThread = 0; //возвращаемое значение потока
T = arguments1->data[(arguments1->size-1)/2]; //меняем местами медиану и значение
arguments1->data[(arguments1->size-1)/2] = arguments1->data[k];//в середине массива
arguments1->data[k] = T;
k = (arguments1->size - 1)/2;
do
{
while (arguments1->data[l] <= arguments1->data[k] && l != k) //все значения меньше медианы остаются //ищем слева от медианы значение больше медианы
{ //за левой границей массива
l++; //ищем слева от медианы значение больше ее
}
while (arguments1->data[r] >= arguments1->data[k] && r != k) //ищем справа от медианы значение меньше медианы
r--;
if (l == k) flag_l = 1; //если какая-то из границ совпала с медианой
if (r == k) flag_r = 1; //устанавливаем соответствующий флаг
T = arguments1->data[l]; //переносим значения меньше медианы влево от медианы
arguments1->data[l] = arguments1->data[r]; //а значения больше медианы вправо от нее
arguments1->data[r] = T;
if (flag_l == 1 && flag_r != 1) //если установлены флаги, это значит, что какая-то из границ совпала с медианой
{ //и после перемены значений переместилась вместе с границей
k = r;
flag_l = 0;
}
else if (flag_l != 1 && flag_r == 1)
{
k = l;
flag_r = 0;
}
}
while (l != r); //продолжаем до тех пор, пока границы не сойдутся
//теперь нужно отсортировать левую и правую части
sortarray(arguments1->data, k); //значения меньше медианы сортирует этот же поток
LPRECORD arg = new RECORD; //создаем параметры для нового потока
memcpy(arg->data, &arguments1->data[k+1], arguments1->size-k-1); //записываем массив значений после медианы
arg->size = arguments1->size - k - 1; //записываем размер массива
if (N < MAXTHREADS) //если к-во потоков не превышает максимально заданное
{
h = CreateThread(NULL, 0, ThSort, arg, 0, &IdThread); //создаем новый поток
N++;
}
else
sortarray(&arguments1->data[k+1], arguments1->size-k-1); //если нельзя создать новый поток, сортируем дедовским способом
delete arg;
CloseHandle(h);
N--;
return IdThread;
}
//////////////////////////////////////////////////
int median(double * array, unsigned int size) //возвращает индекс медианы ряда
{
int i, j, k = 0;
int *count = new int[size];
for(i = 0; i < size; i++)
count[i] = abs(more(array, size, array[i]) - less(array, size, array[i]));
j = count[0];
for (i = 0; i < size; i++)
if (count[i] < j)
{
j = count[i];
k = i;
}
delete count;
return k;
}
//////////////////////////////////////////////////
unsigned int more(double * array, int size, double z) //сколько элементов в массиве
{ //больше заданного числа
unsigned int count = 0;
int i;
for (i = 0; i < size; i++)
if (*(array+i) > z)
count++;
return count;
}
///////////////////////////////////////////////////
unsigned int less(double * array, int size, double z) //сколько элементов в массиве
{ //меньше заданного числа
unsigned int count = 0;
int i;
for (i = 0; i < size; i++)
if (*(array+i) < z)
count++;
return count;
}