АлгоритмыАлгоритмы сортировок. Часть 2

Быстрая сортировка (quicksort)

Быстрая сортировка является одним из самых быстрых алгоритмов сортировки массивов. Скорость работы примерно равна O(n log n) операций при сортировке n элементов.
Описание работы алгоритма:
— Из массива выбираем некоторый опорный элемент p;
— Делим массив на два подмассива, слева от p элементы меньшие либо равные p, а справа — большие либо равные p;
— Для каждого с подмассивов следует проделать ту же операцию, если в них более одного элемента.

Пошаговая работа сортировки:
5 2 7 1|9 3 8 11     // начальная последовательность
5 2 7 1|8 3 9 11
5 2 3 1|8 7 9 11
1 2|3 5|8 7|9 11
1 2|3 5|7 8|9 11     // результат

Реализация алгоритма:
#include <iostream>
#include <cstdlib>  // для Visual C++ заменить на <ctime>
using namespace std;

const int SIZE = 25;
int array[SIZE];

// заполнение массива случайными числами
void GenerationArray()
{
 
// привязка ко времени для генерации чисел без повторений
  srand
(time(0));

 
for (int i=0; i<SIZE; i++)
 
{
   
// заполнение массива числами < 100
    array
[i] = rand()%100;
 
}
}

// вывод массива на экран
void ShowArray()
{
 
for (int i=0; i<SIZE; i++)
 
{
    cout
<< array[i] << " ";
 
}

  cout
<< endl;
}

// High и Low - верхняя и нижняя границы подмассива, который надо отсортировать
void QuickSort(long int High, long int Low)
{
   
long i, j;  // для хранения границ подмассива
   
int p;      // для хранения опорного элемента
   
int temp;

    i
= Low;    // делаем копию нижней границы
    j
= High;   // делаем копию верхней границы

    p
= array[(Low+High)/2];    // выбираем опорный элемент

   
// цикл будет работать, пока границы не пересекутся в массиве
   
do
   
{
       
// если элемент нижней границы меньше опорного элемента,
       
// передвигаем указатель i на один элемент вправо
       
while (array[i] < p) i++;
       
// если элемент верхней границы меньше опорного элемента,
       
// передвигаем указатель j на один элемент влево
       
while (array[j] > p) j--;

       
// если границы не пересеклись по позициям в массиве,
       
// меняем местами элементы i и j
       
if (i <= j)
       
{
            temp
= array[i];
            array
[i] = array[j];
            array
[j] = temp;

            i
++;
            j
--;
       
}
   
} while (i <= j);

   
// если в выделенном подмассиве [Low, j] больше одного элемента,
   
// запускаем рекурсивно функцию QuickSort(long, long)
   
if (j > Low) QuickSort(j, Low);

   
// аналогично
   
if (High > i) QuickSort(High, i);
}

int main()
{
   
GenerationArray();

   
ShowArray();

   
QuickSort(SIZE-1, 0);

   
ShowArray();

   
return 0;
}


Сравнение скорости с сортировкой пузырьком и сортировкой выбором

В прошлой статье я сортировал 100 тысяч элементов сортировкой пузырьком (1 минута 38.731 секунд) и сортировкой выбором (28.313 секунд). Быстрая сортировка отсортировала столько же элементов за 0.024 секунды. Разница заметна :)
На сортировку 10 миллионов элементов ушло 2.333 секунды, в то время как на сортировку пузырьком 10 млн элементов ушло бы почти 23 месяца.
  • +8
  • eReS
  • 05 февраля 2011, 13:20

Комментарии (2)

  • avatar
  • the
  • 06 февраля 2011, 20:55
  • #
  • 0
Если я правильно понял, то при вызове QuickSort в Low передается ноль.
Когда выбирается опорный эл-нт там идёт сложение Low (т.е. нуля) с High.
Для чего там идет сложение с нулём?
Что бы найти средний элемент в подмассиве, к примеру имеем массив с 10 чисел:
p = array[(0+9)/2]; // первый опорный элемент равен 4

То есть пятый элемент по счету. И далее будем делать то же самое с подмассивами, например в 5-ого элемента по 9-тый:
p = array[(5+9)/2]; // второй опорный элемент равен 7

Вот мы нашли следующий опорный элемент. Как видите у нас рекурсивная функция, которая параллельно сортирует левую и правую границы подмассивов:
// если в выделенном подмассиве [Low, j] больше одного элемента,
// запускаем рекурсивно функцию QuickSort(long, long)
if (j > Low) QuickSort(j, Low);

// аналогично
if (High > i) QuickSort(High, i);

Функция имеет общий вид, и нет смысла делать исключение только для первого вызова.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.