Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы / Глава 4_Сорт.doc
Скачиваний:
108
Добавлен:
15.02.2015
Размер:
1.85 Mб
Скачать

4.5.5. Сортировка методом слияния

Метод предназначен для формирования упорядоченного массива при объединении (слиянии) двух уже упорядоченных массивов. Подобные задачи возникают, например, в ситуациях, когда с внешних (медленных) носителей в оперативную память скачиваются части больших массивов, подлежащих объединению и сортировке.

Пусть слиянию в массив подлежат массивыи. Это делается с помощью следующей процедуры. Сравниваются первые (и, значит, наименьшие) элементы, и меньший из них направляется в массив. Так продолжается до исчерпания одного из массивов. После этого оставшаяся часть другого массива отправляется в конец.

Алгоритм сортировки методом слияния содержит следующие этапы.

Ш.1. ― начальные установки индексов

для массивов соответственно.

Ш.2. цикл по ― получение очередного;

если , то

;

;

если , то выйти из цикла;

если , то

;

;

если , то выйти из цикла.

Ш.3. если исчерпан , то дописать воставшиеся;

если исчерпан , то дописать воставшиеся.

Сортировка многопутевым слиянием следующим образом обобщает описанную процедуру. В оперативной памяти выделяются областей, в которых размещаютсяподлежащих слияниюуже упорядоченных массивов:

,…, .

Сначала выбирается минимальный из первых элементов: , записывается первым элементом упорядоченного массива и удаляется из-го массива;-й массив теперь начинается с. Затем снова выбирается минимальный изначальных элементов сливаемых массивов и т. д. Программная реализация предполагает использованиеуказателей на текущие начальные элементы соответствующих массивов.

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

Этот метод эффективен при сортировке массива ключей с лексикографическим упорядочением и для больших значений. Например, колода из 36 карт может быть упорядочена по мастям: П<Т<Б<Ч, а внутри одной масти ― по силе карт: 6<7<8<9<10<в<д<к<т.

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

Пусть лексикографический ключ имеет позиций (разрядов), и в-м разряде может находитьсяразличных символов.

Начнём с примера сортировки карточной колоды из тридцати шести листов. Здесь (масть карты и её значение),=4 (четыре масти);=9. Сначала карты раскладываются на 9 стопок вверх картинкой: в первой стопке шестёрки, во второй семёрки и т.д. Затем стопки кладутся одна на другую: снизу шестёрки, сразу на них семёрки и т. д. Далее карты поочерёдно, начиная с нижней, распределяются по четырём стопкам в зависимости от масти. Наконец стопки складываются в колоду в порядке П-Т-Б-Ч.

Если при последнем распределении две карты оказались в разных стопках, то у них разные масти, и сбор их в колоду сохраняет порядок П-Т-Б-Ч, а значит, и общий порядок. Если же у них одинаковая масть, то поскольку они уже были упорядочены по картинке, то попали в свою стопку в нужном порядке: первой в стопку определённой масти попала шестёрка, затем семёрка и т. д.

Далее рассмотрим случай, когда число элементов , и ключом служит-разрядное число, записанное в системе с основанием. В этом случае.

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

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

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

«Сортировка в лоб» требует дополнительную память для хранения записей.

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

.

Далее резервируется массив для элементов. При следующем проходе ключи со значениемзанимают места с номерами отдо, ключи со значением ― места спо , и т. д.; ключи со значениемзаймут последние мест — с ()-го по -е.

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

В итоге удваивается число проходов, но объём дополнительной памяти составляет ячеек, и ещё требуетсяячеек для счётчиков.

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

Такой подход представляется особенно эффективным, когда число возможных символов в разных разрядах лексикографического ключа различно (как это имеет место, например, для колоды карт ― четыре масти, девять разных значений силы карты). Список для следующего символа просматриваемого разряда организуется при попадании на символ, отличный от предыдущих.

Эффективность сортировки снижается при большом количестве разрядов ключа, в которых мало одинаковых значений.