You are on page 1of 11

Quick sort и Heap sort алгоритми

Въведение
Алгоритми за сортиране

Алгоритмите за сортиране са набор от инструкции, които вземат


масив или списък като вход и подреждат елементите в определен ред.

Сортирането е най -често в числов или в азбучен ред (наречен


лексикографски) и може да бъде във възходящ (AZ, 0-9) или низходящ
(ZA, 9-0) ред.

Сортирането е важен алгоритъм в компютърните науки, тъй


като може да намали сложността на даден проблем. Тези алгоритми
имат директно приложение в алгоритми за търсене, алгоритми на
бази данни, методи за разделяне и завладяване, алгоритми за
структура на данни и много други.

Преди да изберем правилният алгоритъм трябва да определим:

-Какви са изискванията на системата и ней ните ограничения?

-Колко голяма е сортираната колекция?

-Колко памет трябва да се използва?

-Трябва ли масивът да расте?


1. Пирамидално сортиране (Heapsort)

Пирамидално сортиране (Heapsort) се възползва от свой ствата на


структурата на данни в пирамидата (или heap на англий ски), за да
осъществи сортирането на масива.

Heapsort включва изграждане на максимален heap за увеличаване


на сортирането, максималният heap съдържа най -големия елемент
heap в „корена“ на пирамидата. За намаляване на реда за сортиране се
използва минимален heap, кой то съдържа най -малкия heap елемент в
„корена“ на пирамидата.

Стъпките на процеса за сортирането на масива са обобщена по-долу:

Таб.1 Описание на използваните променливи в Heap sort

BuildMaxHeap Функция, позната и като heapify,


изграждаща heap max в масива с
операции O (n).
SWAP Разменя първия елемент от
масива с последния елемент.
Намалява разглеждания обхват
на масива с един.
SiftDown Функция, която по даден индекс
на елемента, го "натиска" надолу
в пирамидата, докато застане на
такава позиция, че никое от
„децата“му (ако има такива) да не
са по-големи от него.
CONTINUE Повтаряме стъпка (2), докато
разглежданият диапазон на
масива не остане само с един
елемент.

Пример:

За да разберем heap сортирането, нека разгледаме несортиран


масив [10, 1, 23, 50, 7, -4] и обсъдим всяка стъпка, предприета за
сортиране на масива във възходящ ред.

На фигурата по-долу е показана heap структурата на входния


масив и максималния heap. Индексният номер на основния heap
елемент е 0. В максималния heap, най -големият елемент на купчината
винаги се намира в корена.
Фиг.1 Heap структурата на масив

След изграждане на първоначалната максимален heap,


последният heap елемент се разменя (swapped) с основния (корена)
елемент и последният елемент, кой то съдържа най -големия брой на
масива, се премахва от heap-а. След това функцията heapify се
използва върху останалите heap елементи, за да ги направи като
максимални heap и така броят на елементите да намалее с един. Този
процес продължава, докато броят на heap елементите не остане един.
В този момент масивът ще бъде сортиран.
Фиг.2 Процес на подреждане на Heap масив

Горната фигура описва премахването на най -големия heap


елемент и образуването и отделянето на максималният heap елемент
от останалите heap елементи. Край ният резултат от процеса е
нарастващ подреден масив.
Фиг.3 Блок схема на Heap Sort алгоритъма (съкратен вид)

Приложение на Heap Sort в С#

using System;

class MyProgram {
// функция heap sort, която извиква функцията heapify, за
да се изгради максимален heap и след това да се размени последният
максимален heap елемент с първия heap елемент
// Изключваме последния heap елемент и възстановяваме heap

static void heapsort(int[] Array) {


int n = Array.Length;
int temp;
for(int i = n/2; i >= 0; i--) {
heapify(Array, n-1, i);
}
for(int i = n - 1; i >= 0; i--) {
// разменяме (swap) последния max-heap елемент с първия heap
елемент
temp = Array[i];
Array[i] = Array[0];
Array[0] = temp;
// изключваме последния heap елемент и възстановяваме heap
heapify(Array, i-1, 0);
}
}

// Функцията heapify се използва за изграждане на max heap


// max heap съдържа най -големият елемент в heap корена, което
означава
// първият елемент на масива е максималният heap

static void heapify(int[] Array, int n, int i) {


int max = i;
int left = 2*i + 1;
int right = 2*i + 2;

//ако левият елемент е по-голям от корена


if(left <= n && Array[left] > Array[max]) {
max = left;
}

//ако десният елемент е по-голям от корена


if(right <= n && Array[right] > Array[max]) {
max = right;
}

//ако max не е i
if(max != i) {
int temp = Array[i];
Array[i] = Array[max];
Array[max] = temp;
//Рекурсивно натрупване на засегнатото поддърво
heapify(Array, n, max);
}
}

// функция за отпечатване на масив


static void PrintArray(int[] Array) {
int n = Array.Length;
for (int i=0; i<n; i++)
Console.Write(Array[i] + " ");
Console.Write("\n");
}

// тестване на кода
static void Main(string[] args) {
int[] MyArray = {10, 1, 23, 50, 7, -4};
Console.Write("Original Array\n");
PrintArray(MyArray);

heapsort(MyArray);
Console.Write("\nSorted Array\n");
PrintArray(MyArray);
}
}

Горният код ще даде следните резултати:

Оригинален масив
10 1 23 50 7 -4
Сортиран масив
-4 1 7 10 23 50

 Сложност на времето (Time Complexity):

Сложността във времето за създаване на heap е Θ (N), а


сложността във времето за създаване на максимален heap е Θ (logN), а
общата времева сложност на heap сортирането е Θ (NlogN).

2. Quick Sort

Алгоритъма за бързото сортиране (Quick sort) е рекурсивен


алгоритъм, кой то на всяка стъпка фиксира/избира един от
подадените елементи, за разделител (pivot), след което разделя
числата на три части - тези по-малки от разделителя, тези равни на
него, и тези по-големи от него. Ако сортираме първата част, след нея
поставим втората част (без да правим нищо върху нея - тя вече е
сортирана, тъй като всички елементи в нея са с равна стой ност), и
накрая сортираме третата част и я поставим след първата и втората, в
край на сметка всички елементи ще са сортирани.

Така стъпките на алгоритъма са:

Таб.2 Описание на използваните променливи в Quick sort

SELECT pivot Избираме един от елементите за


pivot.
Partitioning Пренареждаме масива така, че
всички елементи със стой ности,
по-малки от pivot, да се наредят
преди pivot, докато всички
елементи по-големи от pivot, да
идват след него (равни стой ности
могат да вървят в двете посоки).
След това разделяне, pivot е в
край ното си положение. Това се
нарича операция за разделяне.
Recursive Връщаме се на стъпка 1, като
избираме нов pivot във всяка от
разделените секции, докато
масивът не бъде сортиран

Пример:

За да разберем бързото сортиране, нека разгледаме несортиран


масив [-4, 1, 25, 50, 8, 10, 23] и обсъдим всяка стъпка, предприета за
сортиране на масива във възходящ ред.

Фиг.4 Принцип на работа на Quick sort

В изпълнението на този пример, последният елемент от масива е


избран като pivot елемент. В началото на процеса на разделяне се
създават променливи i и j, които първоначално са еднакви. С
напредването на процеса на разделяне, стой ността на i и j става
различна. i означава границата между елементи, по-малки от pivot и
елементи, по-големи от pivot. j означава границата между елементи,
по-големи от pivot и неразделен масив.

Фиг.5 Разделяне на pivot елементи


След процеса на разделяне, алгоритъма генерира два дяла с дял
от лявата страна, кой то съдържа елементи, по-малки от pivot и
дясната страна, съдържа елементи, по-големи от pivot. И двата дяла
отново са разделени със същата логика и този процес продължава,
докато целият дял получи стой ност нула или един елемент. Край ният
резултат от този процес ще произведе един сортиран масив.

Фиг.6 Блок схема на Quicksort алгоритъма (съкратен вид)

Приложение на Quick Sort в C#

using System;

class MyProgram {
// функция за бързо сортиране, която извиква функция за разделяне
// за подреждане и разделяне на списъка на базата на pivot елемент
// quicksort е рекурсивна функция

static void quicksort(int[] Array, int left, int right) {


if (left < right) {
int pivot = partition(Array, left, right);
quicksort(Array, left, pivot-1);
quicksort(Array, pivot+1, right);
}
}
//функция за разделяне подрежда и разделя списъка
// в два списъка въз основа на pivot елемент
// В този пример е избран последният елемент от списъка
// като pivot елемент. един списък съдържа всички елементи
// по-малки от pivot елемент, кой то съдържа друг списък с
// всички елементи, по-големи от pivot елементd

static int partition(int[] Array, int left, int right) {


int i = left;
int pivot = Array[right];
int temp;

for(int j = left; j <=right; j++) {


if(Array[j] < pivot) {
temp = Array[i];
Array[i] = Array[j];
Array[j] = temp;
i++;
}
}

temp = Array[right];
Array[right] = Array[i];
Array[i] = temp;
return i;
}

// функция за отпечатване на масив


static void PrintArray(int[] Array) {
int n = Array.Length;
for (int i=0; i<n; i++)
Console.Write(Array[i] + " ");
Console.Write("\n");
}

// тестване на кода
static void Main(string[] args) {
int[] MyArray = {-4, 1, 25, 50, 8, 10, 23};
int n = MyArray.Length;
Console.Write("Original Array\n");
PrintArray(MyArray);

quicksort(MyArray, 0, n-1);
Console.Write("\nSorted Array\n");
PrintArray(MyArray);
}
}
Горният код ще даде следния резултат:

Оригинален масив
-4 1 25 50 8 10 23
Сортиран масив
-4 1 8 10 23 25 50

 Сложност във времето (Time Complexity):

Сложността във времето на бързото сортиране е Θ (N²) в най -


лошия случай , а в най -добрия и средния случай е Θ (NlogN).

Заключение

Алгоритмите за сортиране ни дават много начини да подредим


данните си. В край на сметка няма „идеално“ решение за сортирането
на масиви. Правилният алгоритъм се избира на базата на конкретната
задача/условие.

Ако имаме масив с произволно подреждане на стой ности, тогава


Quicksort ще работи най -добре. Quicksort може да бъде внедрен в
прости кодове и множество процесори могат да бъдат използвани за
сортиране на подраздели паралелно.

Ако масивът е вече сортиран, тогава Heapsort ще се справи по-


добри от Quicksort. Това прави Heapsort популярен във вградени
системи и изчисления в реално време

Литература

[1] Sharma, V., S. Singh and K.S. Kahlon. Performance study of improved
HeapSort algorithm and other sorting algorithms on different platforms.

[2] Sepesi, G.. DualHeap sort algorithm: An inherently parallel


generalization of heapsort.

[3] Shahjala and M. Kaykobad. A new data structure or heap sort with
improved numbers of comparisons.

[4] H.-H. Chern, H.-K. Hwang and T.-H. Tsai, An asymptotic theory for
Cauchy-Euler differential equations with applications to the analysis of
algorithmsл

[5] V. Chv´atal, Average-case analysis of quicksort, Lecture notes, Dept. of


Computer Science.

You might also like