TURBO PASCAL |
Новости
|
СлияниеНа сегодняшнем занятии мы начнем рассмотрении темы внешняя сортировка. Внешняя сортировка сортирует файлы, которые не помещаются целиком в оперативную память. Внешняя сортировка сильно отличается от внутренней. Дело в том, что доступ к файлу является последовательным, а не параллельным как это было в массиве. И поэтому считывать файл можно только блоками и этот блок отсортировать в памяти и снова записать в файл. Принципиальную возможность эффективно отсортировать файл, работая с его частями и не выходя за пределы части обеспечивает алгоритм слияния. Под слиянием понимается объединение двух (или более) упорядоченных последовательностей в одну упорядоченную последовательность при помощи циклического выбора элементов, доступных в данный момент. Слияние - намного более простая операция, чем сортировка. Мы рассмотрим 2 алгоритма слияния:
Прямое слияние. Алгоритм Боуза - Нельсона
Пример Исходная последовательность А = 44 55 12 42 94 18 06 67 1 b = 44 55 12 42 2 b = 44 94' 18 55' 3 b = 06 12 44 94' Операция, которая однократно обрабатывает всё множество данных, называется фазой. Наименьший подпроцесс, который, повторяясь, образует процесс сортировки, называется проходом или этапом. В нашем примере сортировка производится за три прохода. Каждый проход состоит из фазы разбиения и фазы слияния. Главным минусом сортировки слиянием является удвоение размера памяти, первоначально занятой сортируемыми данными. Рассмотрим алгоритм с рекурсивным актом слияния, предложенный Боузом и Нельсоном и не требующий резерва памяти. Он основан на очевидной идее: слить две равные упорядоченные части можно слиянием их начальных половин, слиянием конечных и слиянием 2-й половины 1-го результата с 1-й половиной 2-го результата, например: Если части не равны или не делятся точно пополам, процедуру уточняют надлежащим образом. Аналогично слияние "половинок" можно свести к слиянию "четвертушек", "восьмушек" и т. д.; имеет место рекурсия. Const n=200; Естественное (Неймановское) слияние. Она объединяются упорядоченные части,
спонтанно возникшие в исходном массиве; они
могут быть также следствием предыдущей
обработки данных. Рассчитывать на
одинаковый размер сливаемых частей не
приходится. Пример: Пусть даны ключи записей Ищем подсписки В один общий список соединяются 1-й, 3-й, 5-й и т. д. подсписки, в другой - 2-й, 4-й и т. д. подсписки. Произведем слияние 1 подсписка 1 списка и 1 подсписка 2 списка, 2 подсписка 1 списка и 2 подсписка 2 списка и т.д. Будут получены следующие цепи 3 --> 5 --> 7 --> 8 --> 9 и 1 --> 4 --> 7 Подсписок, состоящий из записи "6", пары не имеет и "принудительно" объединяется с последней цепью, принимающей вид 1 --> 4--> 6 --> 7. При нашем небольшом числе записей 2-й этап, на котором сливаются две цепи, окажется последним. В общем случае на каждом этапе подсписок - результат слияния начальных подсписков 1 и 2 списка становится началом нового 1-го списка, а результат слияния следующих двух подсписков - началом 2-го списка. Следующие образуемые подсписки поочередно включаются в 1-й и во 2-й список. Для программной реализации заводят массив sp: элемент sp[i] - это номер записи, которая следует за i-й. Последняя запись одного подсписка ссылается на первую запись другого, а для различения концов подсписков эта ссылка снабжается знаком минус. Repeat {Повторение актов слияний
подсписков} {В конец сформированного подсписка всегда заносится нулевая ссылка (sp[m]:= 0), ибо он может оказаться последним. Действие sp[p]:= -sp[p] обозначает минусом конец ранее построенного подсписка. В переменных i,j ссылки на начала новых сливаемых подсписков - со знаком минус; его снимаем. Переход к новым подспискам требует обновления переменных p, k, r} Итак, на сегодняшнем занятии мы рассмотрели алгоритмы слияния. |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |