Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы сортировки.doc
Скачиваний:
34
Добавлен:
05.11.2018
Размер:
228.35 Кб
Скачать

В этой главе мы разбираем основные понятия и методы, связанные с построением и анализом алгоритмов, на примере двух алгоритмов сортировки – простейшего алгоритма сортировки вставками и более эффективного алгоритма сортировки слиянием.

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

1.1. Алгоритмы

Алгоритм (algorithm) – это формально описанная вычислительная процедура, получающая исходные данные (input), называемые также входом алгоритма или его аргументом, и выдающая результат вычислений на выход (output).

Алгоритмы строятся для решения тех или иных вычислительных задач (computational problems). Формулировка задачи описывает, каким требованиям должно удовлетворять решение задачи, а алгоритм, решающий эту задачу. находит объект, этим требованиям удовлетворяющий.

В этой главе мы рассматриваем задачу сортировки (sorting problem); помимо своей практической важности эта задача служит удобным примером для иллюстрации различных понятий и методов. Она описывается так:

Вход: Последовательность чисел (ai, ay. . . ., а„).

Выход: Перестановка [а\, а^, ... . и',,) исходной последовательности, для которой а\ ^ а^ ^ ... ^ а'„.

Например, получив на вход (31,41,59,26.41,58). алгоритм сортировки должен выдать на выход (26,31.41.41.58,59).

Подлежащая сортировке последовательность называется входом (instance) задачи сортировки.

М

Рис. 1.1. Сортировка карт вставками

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

Алгоритм считают правильным (correct), если на любом допустимом (для данной задачи) входе он заканчивает работу и выдает результат, удовлетворяющий требованиям задачи. В этом случае говорят, что алгоритм решает (solves) данную вычислительную задачу. Неправильный алгоритм может (для некоторого входа) вовсе не остановиться или дать неправильный результат. (Впрочем, неправильный алгоритм может быть полезен, если ошибки достаточно редки. Подобная ситуация встретится нам в главе 33 при поиске больших простых чисел. Но это все же скорее исключение, чем правило.)

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

Мы будем записывать алгоритмы с помощью псевдокода (pseudocode), который напомнит вам знакомые языки программирования (Си, Паскаль, Алгол). Разница в том. что иногда мы позволяем себе описать действия алгоритма «своими словами», если так получается яснее. Кроме того, мы опускаем технологические подробности (обработку ошибок, скажем), которые необходимы в реальной программе, но могут заслонить существо дела.

Сортировка вставками

Сортировка вставками (insertion sort) удобна для сортировки коротких последовательностей. Именно таким способом обычно сортируют карты: держа, в левой руке уже упорядоченные карты и взяв правой рукой очередную карту, мы вставляем её в нужное место, сравнивая с имеющимися и идя справа налево (рис. 1.1).

Запишем этот алгоритм в виде процедуры insertion-sort, параметром которой является массив А[1.. п] (последовательность длины '//,, подлежащая сортировке). Мы обозначаем число элементов в массиве А через leru/f.f^A]. Последовательность сортируется «на месте», без дополнительной памяти (in place): помимо массива мы используем лишь фиксированное число ячеек памяти. После выполнения процедуры insertion-sort массив А упорядочен по возрастанию.

На рис. 1.2 показана работа алгоритма при А = (5,2,4,6,1,3). Индекс j указывает «очередную карту» (только что взятую со стола). Участок Л[1..^'–1] составляют уже отсортированные карты (левая рука), a A[j + 1., та]–ещё не просмотренные. В цикле for индекс j пробегает массив слева направо. Мы берём элемент A[j] (строка 2 алгоритма) и сдвигаем идущие перед ним и большие его по величине элементы (начиная с {j – 1)-го) вправо, освобождая место для взятого элемента (строки 4-7). В строке 8 элемент A[j} помещается на освобождённое место.