Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Быстрая сортировка (Хамитов).docx
Скачиваний:
1
Добавлен:
09.08.2019
Размер:
93.45 Кб
Скачать

Cортировка массива методом Хоара(«Быстрая» сортировка) – сравнение параллельной и последовательной реализации

01.10.2011

Как и для большинства алгоритмов сортировки, методика «быстрой» сортировки взята из повседневного опыта. Чтобы отсортировать большую стопку алфавитных карточек по именам, можно разбить ее на две меньшие стопки относительно какой-нибудь буквы, например K. Все имена, меньшие или равные K, идут в одну стопку, а остальные – в другую.

Данный алгоритм очень удачно подходит для распараллеливания. Меня заинтересовало, какой прирост к производительности будет, если использовать потоки.

Описание «быстрой» сортировки

Подробно о самой сортировке можно прочитать на том же rsdn. Тут коснусь пары основных моментов. Вообще, главное в данной сортировке, что после выбора опорного элемента, слева от него остаются все элементы меньше его, а справа большие. И далее происходит рекурсивный вызов функции сортировки для каждого подмассива. Идея в том, чтобы сортировку обеих частей провести в отдельных поток. Теоретически, в идеальном варианте, когда слева и справа одинаковое число элементов, создавая 2 потока на 2-х ядерном процессоре, скорость выполнения должна увеличиться на 100%.

Алгоритм сортировки

Реализация сортировки наивная, опорным элементом изначально всегда берётся серединный элемент массива. При ветвлении создание потоков для обеих веток не разумно, ибо затраты на создание потока под меньший подмассив превышают время выполнения сортировки подмассива. Можно улучшить алгоритм: создавать поток лишь для большего подмассива, а меньший обрабатывать в текущем потоке.

view sourceprint

01.DWORD __stdcall SortMasP (LPVOID p)

02.{

03.lpArrayParam Params = (lpArrayParam)p;

04.if (Params->left>=Params->right) return 0;

05.int left, right, supporting;

06.int temp;

07.int * mas;

08. 

09.left=Params->left;

10.right=Params->right;

11.mas = Params->mas;

12.supporting=(((lpArrayParam)p)->left+((lpArrayParam)p)->right)/2;

13. 

14.while(Params->left<Params->right)

15.{

16.while ((Params->left<supporting)&&(mas[Params->left]<=mas[supporting]))

17.Params->left++;   // Сдвиг левой границы

18.while ((Params->right>supporting)&&(mas[Params->right]>=mas[supporting]))

19.Params->right--;    // Сдвиг правой границы

20.// Обмен граничных элементов

21.Swap(&mas[Params->left],&mas[Params->right]);

22.// Обновление индекса опорного элемента

23.if (Params->left == supporting ) supporting = Params->right;

24.else if (Params->right == supporting ) supporting = Params->left;

25.}

26.lpArrayParam Params1 = new ArrayParam;

27.Params1->left=left;

28.Params1->right=supporting-1;

29.Params1->mas = mas;

30. 

31.lpArrayParam Params2 = new ArrayParam;

32.Params2->left=supporting+1;

33.Params2->right=right;

34.Params2->mas = mas;

35. 

36.if(TCount<pc)

37.{

38. 

39.HANDLE  thr;

40.InterlockedIncrement(&TCount);

41. 

42.if(Params2->right-Params2->left<Params1->right-Params1->left)

43.{

44.thr = CreateThread(0,0,(LPTHREAD_START_ROUTINE)SortMasP, Params1,0,0);

45.SortMasP(Params2);

46.WaitForSingleObject(thr,  INFINITE);

47.}

48.else

49.{

50.thr = CreateThread(0,0,(LPTHREAD_START_ROUTINE)SortMasP, Params2,0,0);

51.SortMasP(Params1);

52.WaitForSingleObject(thr,  INFINITE);

53.}

54. 

55.InterlockedDecrement(&TCount);

56.CloseHandle(thr);

57. 

58.}

59.else

60.{

61.SortMasP(Params1);

62.SortMasP(Params2);

63.}

64. 

65.delete Params2;

66.delete Params1;

67.return 0;

68.}

Ну, и дополнительные функции/переменные, используемые в методе.

view sourceprint

01.//обмен элементов

02.void Swap(int *a, int *b)

03.{

04.int temp = *a; *a=*b; *b=temp;

05.}

06. 

07.DWORD GetProcessorCount()

08.{

09.SYSTEM_INFO si;

10.GetSystemInfo(&si);

11.return si.dwNumberOfProcessors;

12. 

13.}

14. 

15.DWORD pc=GetProcessorCount(); //число процессоров

16. 

17.//структура для передачи параметров

18.typedef struct _ArrayParam

19.{

20.int left;

21.int right;

22.int * mas;

23. 

24.} ArrayParam, *lpArrayParam;

25. 

26.LONG TCount = 0;    //количество созданных потоков