Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
САОД / Методы сортировки_ЛАБ2.doc
Скачиваний:
32
Добавлен:
26.04.2015
Размер:
333.82 Кб
Скачать

2.2.7. Сортировка распределением

Сортировка распределением интересна тем, что она сортирует массив, не сравнивая элементы друг с другом.

Рассмотрим сначала вырожденный случай сортировки распределением, а затем более общий.

2.2.7.1. Вырожденное распределение

Пусть каждый элемент массива может принимать M(например, от 1 доM) фиксированных значений. Заведем массивAmount, первоначально обнулив его. Затем для каждогоiподсчитаем количество элементов массиваA, равныхi, и занесем это число вAmount[i]:

for i := 0 to M do Amount[i] := 0;

for i := 1 to N do

Inc(Amount[A[i]]);

Теперь в первые Amount[1] элементов массиваAзапишем 1, в следующиеAmount[2] элементов массиваAзапишем 2 и т.д. до тех пор, пока не дойдем до конца массиваA(заметим, что в то же время мы окажемся в конце массиваAmount):

p := 1;

for i := 0 to M do

for j := 1 to Amount[i] do

begin

A[p] := i;

Inc(p);

end;

Несмотря на то, что здесь два внешних цикла на этом участке алгоритма выполняется порядка Nдействий. Это следует из того, что . Поэтому временную сложность метода можно оценить какT(M+N) (Mпоявляется в сумме, так как изначально надо обнулить массивAmount, а это требуетMдействий). Пространственная сложность в этом случае равнаO(M), поскольку требуется дополнительная память размером порядкаM.

Недостатком этого метода является то, что требуется дополнительная память размером порядка M, а это может оказаться недопустимым из-за большого значенияM. Но, еслиM>>N, то есть способ уменьшить объем требуемой дополнительной памяти, который мы сейчас и рассмотрим.

2.2.7.2. Сортировка распределением

Пусть мы можем завести дополнительную память размером M+N, а элементы массива могут принимать значения от 0 доS, причемS>>M.

Каждый элемент этого массива можно представить в M-ичной системе счисления и разбить наKцифр этой системы счисления.

Заведем Mсписков общей суммарной длиной порядкаN(это можно сделать, ограничившись дополнительной памятьюO(M+N)).

Наш алгоритм можно представить следующим образом:

fori:=Kdownto1do

begin

for j := 1 to N do

begin

L:=<i-ой цифреA[j] вM-ной системе счисления>;

... занести A[j] вL-ный список;

end;

... очистить массив A

for j := 1 to M do

... дописать элементы j-ого списка в массивA

end;

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

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

Достигнув i=1, мы получим полностью отсортированный массив.

Как нетрудно заметить, если положить S=M, то отпадает необходимость заводить списки и производить запись в них: вj–ый список будут попадать только числа, равныеj. В этом случае достаточно хранить лишь размеры списков, то есть подсчитать количество элементов, равныхj, для всехjот 1 доS. А потом просто заново заполнить массивAв соответствии с этими количествами. Что мы и делали в случае вырожденной сортировки.

Интересно, что временная сложность этого метода T(K*N), а если учесть, чтоKфактически является константой, то мы получаем гарантированную (минимальную, среднюю и максимальную) линейную сложность. Но недостатком этого метода является необходимость выделять дополнительную память размером порядкаM+N. Если бы не это ограничение, можно было бы считать этот метод самым эффективным при больших значенияхN.