Задача: Улучшение быстрой сортировки
Исходник: Быстрая сортировка QSort4 (оптимизация №2), язык: C++ [code #16, hits: 12010]
автор: this [добавлен: 29.01.2006]
  1. template<class T>
  2. void swap(T* x, int i, int j) {
  3. T tmp;
  4. tmp = x[i]; x[i] = x[j]; x[j] = tmp;
  5. }
  6. int randint(int l, int u) {
  7. srand(time(NULL));
  8. return l + rand() % (u-l + 1);
  9. }
  10.  
  11. const int cutoff = 5;
  12. template<class T>
  13. void QSort4(T* x, int l, int u) {
  14. if (u - l < cutoff)
  15. return;
  16.  
  17. swap(x, l, randint(l, u));
  18. T t;
  19. int i,j;
  20. t = x[l]; i = l; j = u+1;
  21.  
  22. while (1) {
  23. /* пропуск элементов справа и слева,
  24. чтобы не делать лишней работы */
  25. do i++; while (i <= u && x[i] < t);
  26. do j--; while (x[j] > t);
  27.  
  28. if (i > j)
  29. break;
  30. // Делаем swap(i, j):
  31. T tmp;
  32. tmp = x[i]; x[i] = x[j]; x[j] = tmp;
  33. }
  34.  
  35. swap(x, l, j);
  36.  
  37.  
  38. QSort4(x, l, j-1);
  39. QSort4(x, j+1, u);
  40. }
Быстрая сортировка с двусторонним алгоритмом разбиения + случайным выбором элемента разбиения + запретом сортировок малых подмножеств, на которые тратится больше всего времени.

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

cutoff — некоторое небольшое целое число. После завершения работы функции массив будет не отсортирован до конца, но разбит на небольшие группы случайно упорядоченных элементов, причем все элементы одной группы будут меньше любого элемента всех групп, расположенных справа от данной. Сортировать элементы внутри групп нужно каким-то другим методом, и тут лучше всего подходит сортировка вставкой, поскольку массив уже почти упорядочен.

Т.о. для решения задачи сортировки целиком придется выполнить два вызова:
qsort4(0, n-1)
isort3()

Глубина рекурсии в среднем - (log (n-cutoff))
Производительность: ~ O(n*log n)
Расход памяти: ~ O(log (n-cutoff))
Тестировалось на: MS Visual Studio 2005, .NET Framework 2.0

+добавить реализацию