Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
8
Добавлен:
01.05.2014
Размер:
6.19 Кб
Скачать
#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;
}
Соседние файлы в папке Быстрая сортировка