Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы на вопросы по информатике.doc
Скачиваний:
101
Добавлен:
10.05.2014
Размер:
595 Кб
Скачать

Сортировка быстрая («Чем дальше в лес, тем злее дятлы…») Вариант №1 (Вики):

Алгоритм

Быстрая сортировка использует стратегию «разделяй и властвуй». Шаги алгоритма таковы:

  • Выбираем в массиве некоторый элемент, который будем называть опорным элементом.

  • Операция разделения массива: реорганизуем массив таким образом, чтобы все элементы, меньшие или равные опорному элементу, оказались слева от него, а все элементы, большие опорного — справа от него.

  • Рекурсивно упорядочиваем подсписки, лежащие слева и справа от опорного элемента.

Базой рекурсии являются списки, состоящие из одного или двух элементов, которые уже упорядочены. Алгоритм всегда завершается, поскольку за каждую итерацию он ставит по крайней мере один элемент на его окончательное место.

Улучшения

При выборе опорного элемента из данного диапазона случайным образом, худший случай становится очень маловероятным и ожидаемое время выполнения алгоритма сортировки - O(n log n).

Вариант №2 (Forum.Pascal.Net):

Быстрая сортировка Хоара

Это улучшенный метод, основанный на обмене. При "пузырьковой" сортировке производятся обмены элементов в соседних позициях. При пирамидальной сортировке такой обмен совершается между элементами в позициях, жестко связанных друг с другом бинарным деревом. Ниже будет рассмотрен алгоритм сортировки К. Хоара, использующий несколько иной механизм выбора значений для обменов. Этот алгоритм называется сортировкой с разделением или быстрой сортировкой. Она основана на том факте, что для достижения наибольшей эффективности желательно производить обмены элементов на больших расстояниях.

Предположим, что даны N элементов массива, расположенные в обратном порядке. Их можно рассортировать, выполнив всего N/2 обменов, если сначала поменять местами самый левый и самый правый элементы и так далее, постепенно продвигаясь с двух сторон к середине. Это возможно только, если мы знаем, что элементы расположены строго в обратном порядке.

Рассмотрим следующий алгоритм: выберем случайным образом какой-то элемент массива (назовем его X). Просмотрим массив, двигаясь слева направо, пока не найдем элемент a[ i ]>X (сортируем по возрастанию), а затем просмотрим массив справа налево, пока не найдем элемент a[ j ]<X. Далее, поменяем местами эти два элемента a[ i ] и a[ j ] и продолжим этот процесс "просмотра с обменом", пока два просмотра не встретятся где-то в середине массива.

После такого просмотра массив разделится на две части: левую с элементами меньшими (или равными) X, и правую с элементами большими (или равными) X. Итак, пусть a[k] (k=1,...,N) - одномерный массив, и X - какой-либо элемент из a. Надо разбить "a" на две непустые непересекающиеся части а1 и а2 так, чтобы в a1 оказались элементы, не превосходящие X, а в а2 - не меньшие X.

Рассмотрим пример. Пусть в массиве a: <6, 23, 17, 8, 14, 25, 6, 3, 30, 7> зафиксирован элемент x=14. Просматриваем массив a слева направо, пока не найдем a[ i ]>x. Получаем a[2]=23. Далее, просматриваем a справа налево, пока не найдем a[ j ]<x. Получаем a[10]=7. Меняем местами a[2] и a[10]. Продолжая этот процесс, придем к массиву <6, 7, 3, 8, 6> <25, 14, 17, 30, 23>, разделенному на две требуемые части a1, a2. Последние значения индексов таковы: i=6, j=5. Элементы a[1],....,a[i-1] меньше или равны x=14, а элементы a[j+1],...,a[n] больше или равны x. Следовательно, разделение массива произошло.

Описанный алгоритм прост и эффективен, так как сравниваемые переменные i, j и x можно хранить во время просмотра в быстрых регистрах процессора. Наша конечная цель - не только провести разделение на указанные части исходного массива элементов, но и отсортировать его. Для этого нужно применить процесс разделения к получившимся двум частям, затем к частям частей, и так далее до тех пор, пока каждая из частей не будет состоять из одного единственного элемента. Эти действия описываются следующей программой. Процедура Sort реализует разделение массива на две части, и рекурсивно обращается сама к себе...

Сложность O(n*logn), на некоторых тестах работает быстрее сортировки слияниями, но на некоторых специально подобранных - работает за O(n^2).

Примеры:

Type

arrType = Array[1 .. n] Of Integer;

{ первый вариант : }

Procedure HoarFirst(Var ar: arrType; n: integer);

Procedure sort(m, l: Integer);

Var i, j, x, w: Integer;

Begin

i := m; j := l;

x := ar[(m+l) div 2];

Repeat

While ar[i] < x Do Inc(i);

While ar[j] > x Do Dec(j);

If i <= j Then Begin

w := ar[i]; ar[i] := ar[j]; ar[j] := w;

Inc(i); Dec(j)

End

Until i > j;

If m < j Then Sort(m, j);

If i < l Then Sort(i, l)

End;

Begin

sort(1, n)

Type

arrType = Array[1 .. n] Of Integer;

{ второй вариант : }

Procedure HoarSecond(Var ar: arrType; n: Integer);

Procedure Sort(m, l: Integer);

Var i, j, x, w: Integer;

Begin

If m >= l Then Exit;

i := m; j := l;

x := ar[(m+l) div 2];

While i < j Do

If ar[i] < x Then Inc(i)

Else If ar[j] > x Then Dec(j)

Else Begin

w := ar[i]; ar[i] := ar[j]; ar[j] := w;

End;

Sort(m, Pred(j));

Sort(Succ(i),l);

End;

Begin

Sort(1, n)

End;

End;

Соседние файлы в предмете Информатика