Методы сортировки объектов windows. Методы внешней сортировки. Откуда взялось такое необычное название

Скачать Viber 03.04.2019
Скачать Viber

В этой статье мы покажем вам некоторые практические примеры того, как использовать AWK на .

Введение

AWK назван в честь фамилии его авторов: Альфред Ахо, Питер Вайнбергером и Брайан Керниган. AWK очень полезный язык сценариев для обработки текста. Этот язык выполняется в интерпретаторе. Это позволяет пользователю обрабатывать некоторые входные, определять переменные, использовать логические операторы, строки и числовые функции, извлечения данных и создания отформатированных отчетов. Синтаксис AWK очень близок с языку C и является прямым предшественником Perl. Все сценарии AWK могут быть преобразованы в сценарии Perl с использованием утилиты A2P.

Предпосылки

Интерпретатор AWK является стандартным инструментом, найденным на каждом дистрибутиве Linux. Пакет gawk содержит версию AWK с открытым исходным кодом, и в зависимости от дистрибутива Linux он может быть установлен из исходного файла или с помощью пакетов gawk или mawk, включенных в конкретный дистрибутив Linux.

Установка

С правами суперпользователя

Ssh root@IP_Address

Для того, чтобы установить утилиту командной строки AWK на /Fedora или на любую другую на основе RPM распределения Linux, выполните следующую команду:

Yum install gawk

В / , вам нужно вызвать эту команду, чтобы установить Gawk:

Apt-get install gawk

Примеры команды AWK

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

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

Netstat -anp|grep tcp|awk "{print $5}"| cut -d: -f1 | sort | uniq -c | sort -n

Это очень полезно, если вы расследуете, находиться ли ваш сервер под атакой DoS или DDoS.

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

Exim -bpr | grep frozen | awk {"print $3"} | xargs exim -Mrm

Выше команда удалит все замороженные сообщения электронной почты из почтовой очереди Exim.

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

Awk "!x[$0]++" file-with-duplicates > new-file-without-duplicates

Следующая команда напечатает пять случайных чисел от 0 до 999:

Awk "BEGIN { for (i = 1; i <= 5; i++) print int(1000 * rand()) }"

Используйте следующую команду, чтобы подсчитать количество строк в файле с именем «sample_file»:

Awk "END { print NR }" sample_file

Следующая команда выведет все строки в файле «sample_file», которые содержат строки, начинающиеся с ‘ A ‘ или ‘a’, за которыми следует ‘ re’:

Awk "/re/{print}" /opt/sample_file

Вы можете использовать команду AWK для более сложных операций. Если ваш веб-сайт работает довольно медленно, вы можете использовать следующую команду, чтобы проверить, есть ли какая-то проблема с диском I/O (и/или сети, в некоторых редких случаях):

Tac /proc/stat | awk "/^btime/ {up=systime()-$2;print "up " up/86400 "d"}; /^cpu / {print "user " $2/up "%, nice " $3/up "%, sys " $4/up "%, idle " $5/up "%, iowait " $6/up "%, steal " $9/up "%\niowait/used " $6 / ($2+$3+$4) ", steal/used " $9 / ($2+$3+$4) }"

IOWAIT означает, как долго процессы блокируются занятые вводом/выводом, в основном дискового хранения или, возможно, сети. STEAL означает, как долго процессы блокируются удачей CPU Time slice на сервере. Выше iowait на время процессора пользователя (=USER + NICE + SYSTEM) показывает занят ввода / вывода, выше украсть просматривается показывает занят CPU.

Следующий сценарий использует простую команду awk, которая выполняет поиск во входном файле ‘/etc/passwd ‘ и предоставляет вывод с именем пользователя, за которым следует дата и время последнего входа:

Vi login-check #!/bin/bash for user in `awk -F: "{print $1}" /etc/passwd` do echo -n "$user: " finger $user | grep Last if [ $? != 0 ]; then echo fi done

Сделайте скрипт исполняемым:

Chmod 755 login-check

Выполните скрипт:

./login-check

Вы должны состоянии увидеть учетные записи пользователей, доступных на сервере, а затем по дате и времени последнего входа в систему каждого пользователя.

Вывод

Есть некоторые новые языки, такие как Perl и Python, которые могут быть использованы вместо AWK, но использование AWK имеет ряд преимуществ, так как:

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

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

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

В данной статье постараемся это выяснить. Для обеспечения наилучших результатов все представленные алгоритмы будут сортировать целочисленный массив из 200 элементов. Компьютер, на котором будет проводится тестирование имеет следующие характеристики: процессор AMD A6-3400M 4x1.4 GHz, оперативная память 8 GB, операционная система Windows 10 x64 build 10586.36.

Для проведения исследования были выбраны следующие алгоритмы сортировки:

Selection sort (сортировка выбором) – суть алгоритма заключается в проходе по массиву от начала до конца в поиске минимального элемента массива и перемещении его в начало. Сложность такого алгоритма O(n2).

Bubble sort (сортировка пузырьком) – данный алгоритм меняет местами два соседних элемента, если первый элемент массива больше второго. Так происходит до тех пор, пока алгоритм не обменяет местами все неотсортированные элементы. Сложность данного алгоритма сортировки равна O(n^2).

Insertion sort (сортировка вставками) – алгоритм сортирует массив по мере прохождения по его элементам. На каждой итерации берется элемент и сравнивается с каждым элементом в уже отсортированной части массива, таким образом находя «свое место», после чего элемент вставляется на свою позицию. Так происходит до тех пор, пока алгоритм не пройдет по всему массиву. На выходе получим отсортированный массив. Сложность данного алгоритма равна O(n^2).

Quick sort (быстрая сортировка) – суть алгоритма заключается в разделении массива на два под-массива, средней линией считается элемент, который находится в самом центре массива. В ходе работы алгоритма элементы, меньшие чем средний будут перемещены в лево, а большие в право. Такое же действие будет происходить рекурсивно и с под-массива, они будут разделяться на еще два под-массива до тех пор, пока не будет чего разделать (останется один элемент). На выходе получим отсортированный массив. Сложность алгоритма зависит от входных данных и в лучшем случае будет равняться O(n×2log2n). В худшем случае O(n^2). Существует также среднее значение, это O(n×log2n).

Comb sort (сортировка расческой) – идея работы алгоритма крайне похожа на сортировку обменом, но главным отличием является то, что сравниваются не два соседних элемента, а элементы на промежутке, к примеру, в пять элементов. Это обеспечивает от избавления мелких значений в конце, что способствует ускорению сортировки в крупных массивах. Первая итерация совершается с шагом, рассчитанным по формуле (размер массива)/(фактор уменьшения), где фактор уменьшения равен приблизительно 1,247330950103979, или округлено до 1,3. Вторая и последующие итерации будут проходить с шагом (текущий шаг)/(фактор уменьшения) и будут происходить до тех пор, пока шаг не будет равен единице. Практически в любом случае сложность алгоритма равняется O(n×log2n).

Для проведения тестирования будет произведено по 5 запусков каждого алгоритма и выбрано наилучшее время. Наилучшее время и используемая при этом память будут занесены в таблицу. Также будет проведено тестирование скорости сортировки массива размером в 10, 50, 200 и 1000 элементов чтобы определить для каких задач предназначен конкретный алгоритм.

Полностью неотсортированный массив:

Частично отсортированный массив (половина элементов упорядочена):

Результаты, предоставленые в графиках:

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

Для упрощения кода и улучшения читаемости мы введем метод Swap , который будет менять местами значения в массиве по индексу.

Void Swap(T items, int left, int right) { if (left != right) { T temp = items; items = items; items = temp; } }

Пузырьковая сортировка

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

Например, у нас есть массив целых чисел:

При первом проходе по массиву мы сравниваем значения 3 и 7. Поскольку 7 больше 3, мы оставляем их как есть. После чего сравниваем 7 и 4. 4 меньше 7, поэтому мы меняем их местами, перемещая семерку на одну позицию ближе к концу массива. Теперь он выглядит так:

Этот процесс повторяется до тех пор, пока семерка не дойдет почти до конца массива. В конце она сравнивается с элементом 8, которое больше, а значит, обмена не происходит. После того, как мы обошли массив один раз, он выглядит так:

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

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

При следующем проходе обмена не производится, что означает, что наш массив отсортирован, и алгоритм закончил свою работу.

Public void Sort(T items) { bool swapped; do { swapped = false; for (int i = 1; i < items.Length; i++) { if (items.CompareTo(items[i]) > 0) { Swap(items, i - 1, i); swapped = true; } } } while (swapped != false); }

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

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

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

Постепенно отсортированная часть массива растет, и, в конце концов, массив окажется упорядоченным.

Давайте взглянем на конкретный пример. Вот наш неотсортированный массив, который мы будем использовать:

Алгоритм начинает работу с индекса 0 и значения 3. Поскольку это первый индекс, массив до него включительно считается отсортированным.

На этом этапе элементы с индексами 0..1 отсортированы, а про элементы с индексами 2..n ничего не известно.

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

Итак, мы нашли индекс 1 (между значениями 3 и 7). Метод Insert осуществляет вставку, удаляя вставляемое значение из массива и сдвигая все значения, начиная с индекса для вставки, вправо. Теперь массив выглядит так:

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

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

Public void Sort(T items) { int sortedRangeEndIndex = 1; while (sortedRangeEndIndex < items.Length) { if (items.CompareTo(items) < 0) { int insertIndex = FindInsertionIndex(items, items); Insert(items, insertIndex, sortedRangeEndIndex); } sortedRangeEndIndex++; } } private int FindInsertionIndex(T items, T valueToInsert) { for (int index = 0; index < items.Length; index++) { if (items.CompareTo(valueToInsert) > 0) { return index; } } throw new InvalidOperationException("The insertion index was not found"); } private void Insert(T itemArray, int indexInsertingAt, int indexInsertingFrom) { // itemArray = 0 1 2 4 5 6 3 7 // insertingAt = 3 // insertingFrom = 6 // // Действия: // 1: Сохранить текущий индекс в temp // 2: Заменить indexInsertingAt на indexInsertingFrom // 3: Заменить indexInsertingAt на indexInsertingFrom в позиции +1 // Сдвинуть элементы влево на один. // 4: Записать temp на позицию в массиве + 1. // Шаг 1. T temp = itemArray; // Шаг 2. itemArray = itemArray; // Шаг 3. for (int current = indexInsertingFrom; current > indexInsertingAt; current--) { itemArray = itemArray; } // Шаг 4. itemArray = temp; }

Сортировка выбором

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

Давайте посмотрим на работу сортировки выбором на нашем неотсортированном массиве.

При первом проходе алгоритм с помощью метода FindIndexOfSmallestFromIndex пытается найти наименьшее значение в массиве и переместить его в начало.

Имея такой маленький массив, мы сразу можем сказать, что наименьшее значение - 3, и оно уже находится на правильной позиции. На этом этапе мы знаем, что на первой позиции в массиве (индекс 0) находится самое маленькое значение, следовательно, начало массива уже отсортировано. Поэтому мы начинаем второй проход - на этот раз по индексам от 1 до n — 1.

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

Теперь неотсортированная часть массива начинается с индекса 2. Она растет на один элемент при каждом проходе алгоритма. Если на каком-либо проходе мы не сделали ни одного обмена, это означает, что массив отсортирован.

После еще двух проходов алгоритм завершает свою работу:

Public void Sort(T items) { int sortedRangeEnd = 0; while (sortedRangeEnd < items.Length) { int nextIndex = FindIndexOfSmallestFromIndex(items, sortedRangeEnd); Swap(items, sortedRangeEnd, nextIndex); sortedRangeEnd++; } } private int FindIndexOfSmallestFromIndex(T items, int sortedRangeEnd) { T currentSmallest = items; int currentSmallestIndex = sortedRangeEnd; for (int i = sortedRangeEnd + 1; i < items.Length; i++) { if (currentSmallest.CompareTo(items[i]) > 0) { currentSmallest = items[i]; currentSmallestIndex = i; } } return currentSmallestIndex; }

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

Разделяй и властвуй

До сих пор мы рассматривали линейные алгоритмы. Они используют мало дополнительной памяти, но имеют квадратичную сложность. На примере сортировки слиянием мы посмотрим на алгоритм типа «разделяй и властвуй» (divide and conquer) .

Алгоритмы этого типа работают, разделяя крупную задачу на более мелкие, решаемые проще. Мы пользуемся ими каждый день. К примеру, поиск в телефонной книге - один из примеров такого алгоритма.

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

Насколько эффективны эти алгоритмы?

Предположим, что в телефонной книге 1000 страниц. Если вы открываете ее на середине, вы отбрасываете 500 страниц, в которых нет искомого человека. Если вы не попали на нужную страницу, вы выбираете правую или левую сторону и снова оставляете половину доступных вариантов. Теперь вам надо просмотреть 250 страниц. Таким образом мы делим нашу задачу пополам снова и снова и можем найти человека в телефонной книге всего за 10 просмотров. Это составляет 1% от всего количества страниц, которые нам пришлось бы просмотреть при линейном поиске.

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

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

Давайте посмотрим на такой массив:

Разделим его пополам:

И будем делить каждую часть пополам, пока не останутся части с одним элементом:

Теперь, когда мы разделили массив на максимально короткие участки, мы сливаем их в правильном порядке.

Сначала мы получаем группы по два отсортированных элемента, потом «собираем» их в группы по четыре элемента и в конце собираем все вместе в отсортированный массив.

Для работы алгоритма мы должны реализовать следующие операции:

  1. Операцию для рекурсивного разделения массива на группы (метод Sort).
  2. Слияние в правильном порядке (метод Merge).

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

Public void Sort(T items) { if (items.Length <= 1) { return; } int leftSize = items.Length / 2; int rightSize = items.Length - leftSize; T left = new T; T right = new T; Array.Copy(items, 0, left, 0, leftSize); Array.Copy(items, leftSize, right, 0, rightSize); Sort(left); Sort(right); Merge(items, left, right); } private void Merge(T items, T left, T right) { int leftIndex = 0; int rightIndex = 0; int targetIndex = 0; int remaining = left.Length + right.Length; while(remaining > 0) { if (leftIndex >= left.Length) { items = right; } else if (rightIndex >= right.Length) { items = left; } else if (left.CompareTo(right) < 0) { items = left; } else { items = right; } targetIndex++; remaining--; } }

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

Быстрая сортировка - это еще один алгоритм типа «разделяй и властвуй». Он работает, рекурсивно повторяя следующие шаги:

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

Давайте посмотрим на работу алгоритма на следующем массиве:

Сначала мы случайным образом выбираем ключевой элемент:

Int pivotIndex = _pivotRng.Next(left, right);

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

Перемещение значений осуществляется методом partition .

На этом этапе мы знаем, что значение 6 находится на правильной позиции. Теперь мы повторяем этот процесс для правой и левой частей массива.

У нас осталось одно неотсортированное значение, а, поскольку мы знаем, что все остальное уже отсортировано, алгоритм завершает работу.

Random _pivotRng = new Random(); public void Sort(T items) { quicksort(items, 0, items.Length - 1); } private void quicksort(T items, int left, int right) { if (left < right) { int pivotIndex = _pivotRng.Next(left, right); int newPivot = partition(items, left, right, pivotIndex); quicksort(items, left, newPivot - 1); quicksort(items, newPivot + 1, right); } } private int partition(T items, int left, int right, int pivotIndex) { T pivotValue = items; Swap(items, pivotIndex, right); int storeIndex = left; for (int i = left; i < right; i++) { if (items[i].CompareTo(pivotValue) < 0) { Swap(items, i, storeIndex); storeIndex += 1; } } Swap(items, storeIndex, right); return storeIndex; }

Заключение

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

МОУ СОШ С. КАМЫШКИ

ТВОРЧЕСКАЯ РАБОТА

Методы сортировки данных

в курсе ОИВТ

Выполнила:

учитель информатики

На I квалификационную категорию

с. Ал-Гай, 2006

Введение. 3

1. Необходимость изучения темы "Методы сортировки данных". 4

2. Подготовительная работа к теме "Методы сортировки данных". 4

3.Методы сортировок. 7

4. Более сложные и более эффективные методы сортировки. 10

5. Сравнительная характеристика методов сортировки. 11

Заключение. 12

ЛИТЕРАТУРА.. 13

Приложение. 14

Приложение. 15

Приложение. 16

Приложение. 20

Приложение. 21

Приложение. 24

Приложение. 26

Приложение. 28

Приложение. 29

Приложение. 34

Приложение. 37

Приложение. 42

Введение

В этой работе рассматривается большая тема "методы сортировки данных", которая является обязательной в курсе ОИВТ
Изучение табличных величин и методов сортировки - неотъемлемая часть любого курса информатики. Это видно хотя бы по тому факту, что эта тема рассматривается во всех распространенных сегодня учебниках, несмотря на различия в идейных и методических установках их авторов.
Процессом сортировки называют действия по упорядочению некоторых данных (таблицу) по ключу. Ключи могут быть разными. Например, преобразовать
1) таблицу чисел по возрастанию,
2) таблицу фамилий - по алфавиту , причем только по первой букве,
3) элементы, стоящие только на четных местах таблицы в убывающем порядке.
Очевидно, что с "отсортированными" данными работать легче и быстрее, чем с произвольно расположенными. Когда элементы "отсортированы", проще найти, например, телефон товарища в телефонной книге на 500 страниц, быстрее найти слово в словаре на 700 страниц.

Важность темы "сортировки" определяется и особой ролью таблиц. Все применения ЭВМ основаны на их способности к быстрой и точной обработке больших объемов информации, а это возможно только когда информация однородна и отсортирована. Таким образом, таблицы как основное средство представления однородной информации неизбежно используются во всех реальных компьютерных программах.
На табличном принципе основана и архитектура современных ЭВМ: память машины можно рассматривать как большой массив байтов, адреса которых располагаются по возрастанию. Следовательно, без понимания информационной сущности таблиц и основных алгоритмов их обработки невозможно формирование полноценных представлений о возможностях ЭВМ и принципах их работы. Отсюда вытекает необходимость темы "Сортировки " в общеобразовательном курсе информатики. Абсолютно необходима эта тема и в углубленном курсе информатики. Для построения сколько-нибудь сложных и содержательных программ необходимо уверенное владение общими принципами применения таблиц и базовыми приемами их обработки.
Элементы сортировки данных излагаются во многих работах различных авторов (см.). Это указывает на актуальность темы "сортировка", изучение их методов, разработки методики преподавания тем из курса ОИВТ, связанных с сортировкой данных.
В МОУ СОШ с. Камышки информатика преподается на протяжении многих лет. За эти годы нам не раз приходилось изменять программу. Иногда приходилось изменять методику изложения и содержание материала, что частично связано с развитием вычислительной техники и появляющимися в связи с этим новыми возможностями и новыми технологиями .

Тема "сортировки" является неотъемлемой частью программы. У учителя имеется большое количество заготовленных алгоритмов решения тех или иных задач. В процессе изучения темы оказывается эффективным: выполнение учеником готовых алгоритмов и программ самому, "вместо компьютера", выполнение "трассировки" алгоритма для тех или иных исходных данных, подбор таких данных, для которых алгоритм будет выполнять наибольшее или наименьшее возможное количество действий. Для каждой темы такая работа не только с компьютером, но и с тетрадью дает, по мнению автора, положительный результат.
Целью данной работы является изложение методики преподавания в 10-11 классах темы "Сортировки элементов", а также тем, связанных с сортировкой данных.
Кроме того, на примере этой темы хотелось бы продемонстрировать ту методику преподавания, которая используется и при преподавании многих других тем.
Методы "быстрой" сортировки, которые являются более сложными для понимания, изучаются на факультативных занятиях.

1. Необходимость изучения темы "Методы сортировки данных"

Изучение любой темы следует начинать с того, чтобы подвести ученика к необходимости этого, показать потребность в решении соответствующего круга проблем, привести доступные для понимания учеников примеры, продемонстрировать использование элементов сортировки в прикладных задачах (на практике, в окружающем нас мире).
Как только мы дали еще интуитивное понятие смысла "сортировки" данных, мы говорим на уроках ОИВТ о ее необходимости, например, сортировки данных по какому-либо признаку. Мы приводим примеры организации личных записных книжек, словарей, телефонных справочников , математических таблиц, энциклопедий. Трудно себе представить, как пользоваться перечисленными объектами, если информация в них не была бы отсортирована.
В словарях слово "сортировка" определяется как распределение, отбор по сортам, качеству, размерам, по сходным признакам, в программировании это слово традиционно используется в более узком смысле.
Под сортировкой в курсе ОИВТ обычно понимают процесс размещения элементов заданного множества объектов в некотором определенном порядке, как правило, в порядке возрастания или убывания (когда сортируемыми элементами являются числа) или в алфавитном порядке (при сортировке текстовой информации).
Очевидно, что отсортированными данными легче пользоваться, чем произвольно расположенными данными. Когда элементы отсортированы, их проще отыскать, проще производить с ними различные операции. В отсортированных данных легче определить, имеются ли пропущенные элементы. Для двух отсортированных таблиц легче найти общие элементы.
Сортировка также является мощным средством ускорения работы практически любого алгоритма, в котором возникает необходимость частого обращения к определенным элементам. Как пишет один из классиков теории программирования Д. Кнут в [ 4 ] "Даже если бы сортировка была почти бесполезна, нашлась бы масса причин заняться ею! Изобретательные методы сортировки говорят о том, что она и сама по себе интересна как объект исследования". Анализ этих методов очень полезен и с точки зрения обучения, так как с их помощью можно наглядно проиллюстрировать самые разные ситуации. По словам создателя языка Паскаль, Н. Вирта, "создается впечатление, что можно построить целый курс программирования, выбирая примеры только из задач сортировки" [ 5 ].
Интересен этот класс алгоритмов еще и тем, что на нем наглядно демонстрируются богатейшие возможности программирования: насколько разными путями можно прийти к одной цели - получение упорядоченного массива! На множестве алгоритмов сортировки становится понятной необходимость сравнительного анализа алгоритмов и оценки их качества, критериями которого являются увеличение быстродействия и экономии памяти. Недаром вопросы, связанные с сортировкой, занимают важное место в школьном курсе информатики

2. Подготовительная работа к теме "Методы сортировки данных".

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

Возможная вводная задача для темы "Таблицы" - нахождение периметра многоугольника с известными длинами сторон изложена в приложение 1. Эта задача подводит учеников к основным свойствам табличных величин: таблица состоит из множества простых переменных, к которым можно обращаться не по уникальным именам, а по общему имени таблицы с указанием номера элемента.

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

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

Однородность означает, что все элементы таблицы равноправны: имеют одинаковый, содержательный смысл, при обработке над ними совершаются одинаковые операции.

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

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

Общность условий обеспечивает распознавание задачи учеником, отнесение ее к конкретному типу, то есть создает возможность реального применения классификации.
Общность решений помогает ученику сделать следующий шаг - подобрать метод решения, то есть обеспечивает результативность классификации.
Таким образом, в основу классификации должен лечь некий признак, явно видимый из условия задачи и существенно влияющий на ее решение. В качестве такого признака предлагается рассматривать информационную роль таблицы в алгоритме, то есть вид табличной величины.
Очевидно, что таблица может быть результатом алгоритма(заполнение), аргументом (обработка) и аргументом-результатом (модификация). При более внимательном рассмотрении становится ясно, что обработка (таблица - аргумент) включает слишком большой класс задач, решаемых разными методами. Среди них можно выделить две большие группы: задачи анализа и задачи поиска. В задачах анализа требуется просмотреть всю таблицу и определить какие-то ее характеристики (сумма, произведение, количество элементов с заданным свойством и т. д.) В задачах поиска требуется найти в таблице элемент, обладающий нужным свойством, причем просматривать всю таблицу для этого необязательно.
С другой стороны, многие задачи модификации не требуют освоения специальных приемов и сводятся к комбинации анализа и заполнения. Это, например, известная задача о корректировке отчета (элементы, меньшие100, заменить на 100) и ей подобные. Поэтому выделять модификацию как отдельный класс задач не стоит.
Реальный интерес представляют задачи перестановки, в которых необходимо переставить элементы заданной таблицы в соответствии с какими-то требованиями. Эти задачи не сводятся к другим и могут рассматриваться как самостоятельная группа. Главная задача перестановки - это сортировка элементов массива, то есть элементы массива необходимо переставить так, чтобы они располагались, например, по возрастанию. Задача сортировки массивов не падает с неба, а относится к одной из групп задач на табличные величины. Окончательно получаем такие группы задач:
1. Заполнение
2. Анализ
3. Поиск
4. Перестановка.
Серия задач для каждой группы приведена в приложении 3.

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

Опыт работы за многие годы показал, что кроме составления алгоритмов и программ учителем и учениками желательно уделять большое внимание выполнению готовых алгоритмов.
Учащиеся при этом "обязаны":
1) выполнить алгоритм,
2) определить, что получается при его выполнении на конкретных данных,
3) восстановить условие задачи по готовому алгоритму,
4) проанализировать количество "элементарных" действий при выполнении алгоритма, что отражает скорость работы алгоритма или время его выполнения,
5) подобрать такие данные, для которых количество "элементарных" действий будет минимальным и такие данные, для которых он будет максимальным.

С готовыми алгоритмами можно работать в различных формах, например:
1. при объяснении всем учащимся одного и того же алгоритма;
2. при работе с учеником индивидуально;
3. при объяснении отдельной темы, ученикам, которые пропустили тему, например, по причине болезни;
4. при уяснении темы с теми учащимися, которые не всегда с первого раза усваивают материал.
Работа в различных формах с готовыми алгоритмами позволяет:
1. учитывать индивидуальные особенности учеников;
2. учитывать психологию, их различную по времени реакцию;
3. развивать их логические, алгоритмические способности;
4. углубить знания по соответствующей теме, так как для получения результата он обязан сам, как исполнитель выполнить алгоритм, а значит закрепить все конструкции, глубже понять, как они выполняются, какие особенности имеют.

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

Итак в первый год обучения (в 10 классе) заложен фундамент изучения таблиц, проработкой серии задач и алгоритмов на выбор максимальных и минимальных элементов, перестановку элементов и т. д.
В 11-ом классе - мы вплотную подходим к методам сортировки, опираясь на изученные алгоритмы обработки таблиц.
Рассматриваются задачи поиска нужного элемента, составление словарей, справочников, составление лотерейных таблиц, списка учеников в журнале.
Для решения многих задач удобно сначала упорядочить данные по определенному признаку.
Данные, например, элементы массива, можно отсортировать:
по возрастанию - каждый следующий элемент больше предыдущего:
а[ 1 ] < a < a[n];
по неубыванию - каждый следующий элемент не меньше предыдущего:
а <= а <=. . .<= а[n];
по убыванию - каждый следующий элемент меньше предыдущего:
а [ 1 ]> а> ... >а[n],
по невозрастанию - каждый следующий элемент не больше предыдущего:
а [ 1 ] >= а >= ... >=a[n].

3.Методы сортировки

Существует довольно много различных методов сортировки, отличающихся друг от друга степенью эффективности, под которой понимается количество сравнений и количество обменов, произведенных в процессе сортировки, время выполнения и объем занимаемой ОП. Рассмотрим подробно некоторые из указанных методов. Сначала приведены четыре простых метода. Каждый учитель может выбирать любой порядок изучения указанных методов, если предложенный порядок не устраивает.
Однако, перед тем как рассматривается любой из метод сортировки необходимо повторить отдельных уже изученных алгоритмов, на которые этот метод опирается.
Сначала рассмотрим два метода сортировки:
сортировку выбором (или линейную) и сортировку обменом (или пузырьковую).
Оба метода не очень эффективны и на практике используются крайне редко. Но тогда почему ими нужно вообще заниматься? Во-первых, во многих простых случаях (например, когда требуется отсортировать всего 20-25 чисел) они вполне удовлетворительны. Во-вторых, эти методы интересны для нас тем, что в них моделируется естественное поведение человека, осуществляющего сортировку в ручную. Именно эти два метода легче всего описываются в форме четких алгоритмов и приводят к простой программной реализации.

Рассмотрим сортировку выбором.

Сортировка выбором состоит в том, что сначала в неупорядоченной последовательности выбирается минимальный элемент. Этот элемент исключается из дальнейшей обработки, а оставшаяся последовательность элементов принимается за исходную, и процесс повторяется до тех пор, пока все элементы не будут выбраны. Очевидно, что выбранные элементы образуют упорядоченную последовательность. Выбранный в исходной последовательности минимальный элемент размещается на предназначенном ему месте упорядоченной последовательности несколькими способами:
1. Минимальный элемент после i-го просмотра перемещается на i-е место (i=1, 2 , 3, другого массива, а в старом, исходном, на месте выбранного размещается какое-то очень большое число, превосходящее по величине любой элемент сортируемого массива. Измененный таким образом массив принимается за исходный, и осуществляется следующий просмотр. Очевидно, что при этом размер обрабатываемого массива на 1 меньше размера предыдущего.
2. Минимальный элемент после i-го просмотра перемещается на i-ое место (i=1, 2, 3, заданного массива, а элемент с i-го места - на место выбранного. После каждого просмотра упорядоченные элементы (от первого до элемента с индексом i) исключаются из дальнейшей обработки, т. е. размер каждого последующего обрабатываемого массива на 1 меньше размера предыдущего.
Этот метод сортировки обычно применяется для массивов, не содержащих повторяющихся элементов. Для достижения поставленной цели можно действовать следующим образом:
1) выбрать максимальный элемент массива;
2) поменять его местами с последним элементом (после этого наибольший элемент будет стоять на своем месте);
3) повторить пункты. 1-2 с оставшимися п-1 элементами, то есть рассмотреть часть массива, начиная с первого элемента до предпоследнего, найти в ней максимальный элемент и поменять его местами с предпоследним; (п-1)-м элементом массива и так далее, пока не останется один элемент, уже стоящий на своем месте.
Всего потребуется п-1 раз выполнить эту последовательность действий. В процессе сортировки будет увеличиваться отсортированная часть массива, а не отсортированная, соответственно, уменьшаться.

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

Алгоритмы, реализующие этот метод, рассмотрены в приложении 5.
Можно предложить ученикам:
1. Подсчитать количество произведенных сравнений типа А[I] < AF.
2. Подсчитать количество произведенных перестановок типа Swap (A, B).
Проанализировав первый и второй способы с точки зрения эффективности алгоритма, который выражается в наименьшем количестве выполняемых пересылок и сравнений, вместе с учениками следует записать ещё один, третий способ сортировки выбором (см. приложение 5).
Ход сортировки третьим способом для сортировки массива 30, 17, 73, 47, 22, 11, 65, 54 отразим в таблице

На последующих уроках информатики следует закрепить изученный метод сортировки выбором.

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

Рассмотрим сортировку обменом (метод "Пузырька").

Сортировка обменом - метод, при котором все соседние элементы массива попарно сравниваются друг с другом и меняются местами в том случае, если предшествующий элемент больше последующего. В результате этого максимальный элемент постепенно смещается вправо и, в конце концов, занимает свое крайне правое место в массиве, после чего он исключается из дальнейшей обработки. Затем процесс повторяется, и свое место занимает второй по величине элемент, который также исключается из дальнейшего рассмотрения. Так продолжается до тех пор, пока вся последовательность не будет упорядочена.
Если последовательность сортируемых чисел расположить вертикально (первый элемент - внизу) и проследить за перемещениями элементов (рис. 2 в приложении 6), то можно увидеть, что большие элементы, подобно пузырькам воздуха в воде, "всплывают" на соответствующую позицию. Поэтому "сортировку", таким образом, называют еще сортировкой методом "пузырька", или "пузырьковой" сортировкой.
Сортировка методом простого обмена может быть применена для любого массива.
Итак, в сортировке "обменом" все соседние элементы попарно сравниваются друг с другом и меняются местами, если предшествующий элемент больше последующего. То есть мы опять основываемся на уже отработанных алгоритмах перестановки элементов.
Описание этого метода подробнее в приложении 6.

"Шейкер" - сортировка.

Несмотря на все сделанные выше усовершенствования, "пузырьковая" сортировка следующего (почти упорядоченного!) массива 5, 7, 12, 28, 36, 85, 2 будет проведена за семь проходов. Это связано с тем, что при сортировке, рассматриваемым методом, за один проход элемент не может переместиться влево больше чем на одну позицию. Так что если минимальный элемент массива находится в его правом конце (как в рассматриваемом примере), то придется выполнить максимальное число проходов. Поэтому естественно напрашивается еще одно улучшение метода "пузырьковой" сортировки - попеременные проходы массива в обоих направлениях, а не только от его начала к концу. В этом случае время сортировки может несколько сократиться. Такой метод сортировки называется "шейкер"-сортировкой (от английского слова shake - трясти, встряхивать). Его работа показана на примере сортировки массива из 8 элементов (на рис. 3 в приложении 7). Алгоритмы этого метода подробно изложены в приложении 7.

Сортировка подсчетом

Этот простой и легкий для понимания метод заключается в том, что каждый элемент массива сравнивается со всеми остальными. Место каждого элемента в отсортированном массиве зависит от числа элементов, меньших его. Иными словами, если некоторый элемент превышает 13 других, то его место в упорядоченной последовательности - 14. Следовательно, для сортировки необходимо сравнить попарно все элементы и подсчитать, сколько из них меньше каждого отдельного элемента. После этого все элементы исходного массива можно разместить на соответствующих им местах в новом, специально созданном массиве. Алгоритм сортировки подсчетом подробно изложен в приложении 8.

Сортировка вставками (методом прямого включения).

Сортировка вставками, так же как и сортировка методов простого выбора, обычно применяется для массивов, не содержащих повторяющихся элементов. Сортировка методом прямого включения, как и все описанные выше, производится по шагам. На k-м шаге считается, что часть массива, содержащая первые k-1 элементов, уже упорядочена, то есть a < a< . . . < a. Далее необходимо взять k-й элемент и подобрать для него такое место в отсортированной части массива, чтобы после его вставки упорядоченность не нарушилась, то есть надо найти такое j (1<=j<=k-1), что a<=a[k]

Более подробно этот метод рассмотрен в приложении 9

4. Более сложные и более эффективные методы сортировки.

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

Обменная сортировка с разделением (сортировка Хоара)

Сортировка методом простого обмена (методом "пузырька") является в среднем самой неэффективной. Это обусловлено самой идеей метода, который требует в процессе сортировки сравнивать и обменивать между собой только соседние элементы. Можно существенно улучшить метод сортировки, основанный на обмене. Это улучшение приводит к самому лучшему на сегодняшний день методу сортировки массивов, который можно назвать обменной сортировкой с разделением. Он основан на сравнениях и обменах элементов, стоящих на возможно больших расстояниях друг от друга. Предложил этот метод Ч. в 1962 году. Поскольку производительность этого метода впечатляюща, автор назвал его "быстрой сортировкой".
Более подробно этот метод рассмотрен в приложении 10.

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

Существует еще один метод сортировки элементов массива, эффективность которого сравнительно велика, - метод слияний.
Перед тем как давать этот метод сортировки, ученикам модно предложить следующую задачу, которая когда-то была олимпиадной, а теперь решается на обычных уроках.:
Причем с минимальным количеством сравнений. На алгоритме этой задачи, которую могут решить сами ученики без подсказки учителя, и построен метод слияния.
Конечно, можно решить задачу, используя метод вставок - каждый элемент массива А разместить на соответствующем ему месте в массиве В. Однако, при этом количество сравнений превысит n+m.
Способ решения задачи изложен в приложении11.

Метод сортировки "слиянием" состоит в разбиении данного массива на несколько частей, которые сортируются по отдельности и впоследствии "сливаются" в одну.

Пусть массив а разбивается на части длиной k, тогда первая часть - a[I], a , . . ., a [k], вто-рая - a, a,..., a и так далее. Если n не делится на k, то в последней части будет менее k элементов.
После того как массивы-части упорядочены, можно объединить их в упорядоченные массивы-части, состоящие не более чем из 2k элементов, которые далее объе-динить в упорядоченные массивы длиной не более 4k, и так далее, пока не получится один упорядоченный массив. Таким образом, чтобы получить отсортированный массив этим методом, нужно многократно " сливать" два упорядоченных отрезка массива в один упорядоченный отрезок. При этом другие части массива не затрагиваются. Более подробно этот метод как факультативный материал рассмотрен в приложении 12.

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

Вспомним один из простых методов - метод подсчета. Поскольку этот метод, несмотря на усовершенствование, требует сравнения всех пар элементов, то продолжительность сортировки массива из n элементов будет пропорциональна n2. Несколько лучшие показатели имеют методы сортировки вставками, обменом и выбором, однако и в них продолжительность работы процедур также пропорциональна n2. Вместе с тем можно показать, что время, затрачиваемое на упорядочивание массива такими методами, как, например, быстрая сортировка или пирамидальная сортировка, пропорционально n log2n, т. е. значительно меньше. Поэтому все рассмотренные методы сортировки подразделяют на простые (n2) и усовершенствованные, или "логарифмические" (n log2n) .
Подробный анализ основных методов сортировки проведен в работах . В качестве показателей для оценки того или иного метода в них используются количество сравнений и количество перемещений элементов в ходе сортировки. Однако эти характеристики не учитывают затрат времени на другие операции, такие, как управление циклами, и др. Очевидно, что критерием для сравнения различных методов является время, затрачиваемое на сортировку. Данные о времени выполнения процедур сортировки получены Н. Виртом .
Конечно, современные компьютеры работают значительно быстрее, чем тогда, когда были проведены расчеты, т. е. данные, приведенные в , устарели. В то же время относительные показатели различных методов в целом не изменились. В приложении 12 представлены относительные характеристики девяти вариантов методов сортировки, полученные на основе результатов, приведенных Н. Виртом.
Приведенные данные демонстрируют явное различие методов: n2 и n log2n. Из таблицы 1 видно, что наилучшим среди простых методов является сортировка вставками, среди усовершенствованных - быстрая сортировка.
Н. Вирт отмечает также следующее:
- "пузырьковая" сортировка является наихудшей среди всех сравниваемых методов. Ее улучшенный вариант - "шейкер" - сортировка - все-таки хуже, чем сортировка простыми вставками и сортировка выбором;
- особенностью быстрой сортировки является то, что она сортирует массив с элементами, расположенными в обратном порядке практически так же, как и отсортированный в прямом порядке.
Следует добавить, что приведенные результаты были получены при сортировке числовых массивов. Если же значением элементов массива являются данные типа "запись", в которых сопутствующие поля (компоненты) занимают в 7 раз больше памяти, чем числовое поле, по которому проводится сортировка, то картина изменится.
В таблице 2 даны сравнительные характеристики методов сортировки массивов данных типа "запись".
Видно, что
1) сортировка выбором дает существенный выигрыш и оказывается лучшим из простых методов;
2) "пузырьковая" сортировка по-прежнему является наихудшим методом;
3) быстрая сортировка даже укрепила свою позицию в качестве самого быстрого метода и оказалась действительно лучшим алгоритмом сортировки.

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

В основе методов внешней сортировки лежит процедура слияния, заключающаяся в объединении двух или более отсортированных последовательностей. Рассмотрим эту процедуру на примере слияния двух последовательностей A и B в последовательность C. Пусть элементы A и B отсортированы по возрастанию, то есть a 1 £ a 2 £ …£ a m и b 1 £ b 2 £ …£ b n . Требуется, чтобы последовательность C также располагалась по возрастанию, то есть выполнялось c 1 £ c 2 £ …£ c m + n .

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

Можно заметить, что доступ к элементам A, B и C выполнялся строго последовательно. В методах внешней сортировки в качестве последовательностей A, B и C фигурируют отсортированные участки файлов.

Базовым методом внешней сортировки является метод простого слияния. Рассмотрим его на следующем примере. Пусть имеется файл A, включающий элементы 27, 16, 13, 11, 18, 25, 7. Этот файл разделяется на два файла B и C путем поочередной записи элементов в эти файлы. Покажем это схемой

B: 27, 13, 18, 7

A: 27, 16, 13, 11, 18, 25, 7

Затем файлы B и C снова соединяются путем поочередного включения в C элементов из A и B. При этом первым располагается меньший элемент каждой пары. Получится следующий результат

B: 27, 13, 18, 7

Пары отделяются друг от друга апострофами. На следующем этапе снова происходит разделение файла A на B и C, но в каждый файл пишутся поочередно уже не отдельные элементы, а выделенные пары. Получаем

B: 16, 27,’ 18, 25

A: 16, 27,’ 11, 13,’ 18, 25, ‘ 7



B: 16, 27,’ 18, 25

A: 11, 13, 16, 27,’ 7, 18, 25

Затем файл A распределяется по четверкам элементов и при новом соединении будет состоять из упорядоченных восьмерок элементов. В нашем примере сортировка закончится на этом этапе. В общем случае длина отсортированных серий будет увеличиваться по степеням 2, пока величина серии не превзойдет количество элементов в файле.

На этом примере определим основные термины внешней сортировки. В методе участвовали 3 файла, поэтому он называется трехленточным. Для выполнения сортировки потребовалось 3 прохода. Отдельный проход состоял из процедур разделения и слияния, каждая из которых обрабатывала все элементы. Такие процедуры называют фазами. Следовательно, метод простого слияния является двухфазным и трехленточным.

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

Как видно из приведенных выше данных, метод может конкурировать по скорости с самыми быстрыми методами внутренней сортировки, но не применяется в таком качестве, так как требует значительных затрат памяти. Число проходов оценивается величиной log 2 n, а общее число пересылок M пропорцинально n log 2 n.

Метод простого слияния не дает какого-либо выигрыша в тех случаях, когда файл A полностью либо частично отсортирован. Этот недостаток отсутствует в методе естественного слияния.

Назовем серией последовательность элементов a i , a i +1 , …, a j , удовлетворяющих соотношениям a i -1 > a i £ a i +1 £ …£ a j > a j +1 . В частных случаях серия может находиться в начале или конце последовательности.

Исходный файл A разбивается на серии. Распределение на B и C ведется по сериям. При соединении сливаются пары серий. Снова возможен как трехленточный, так и четырехленточный вариант метода. Ниже показан пример сортировки методом естественного слияния c 4 лентами.

B: 17, 25, 41, ‘6

A: 17, 25, 41, ‘ 9, 11, ‘ 6, ‘ 3, 5, 8, 44

C: 9, 11, ‘ 3, 5, 8, 44

A: 9, 11, 17, 25, 41 B: 3, 5, 6, 8, 9, 11, 17, 25, 41, 44


D: 3, 5, 6, 8, 44 C:

При последнем разделении лента C оказывается пустой, и отсортированный файл остается на ленте B.

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

Program SortSlian;

{ 3-ленточная, 2-фазная сортировка естественным слиянием }

{ ключи целые и положительные }

Type elem=record

{ другие поля }

tape=file of elem;

Name: string; { имя исходного файла }

Procedure Vvod(var F: tape);

While K <> -1 do

Write("Введите очередной ключ (конец -1): ");

if K<>-1 then Write(F, S)

Procedure Pech(var F: tape);

While not eof(F) do

Write(S. Key," ")

Procedure CopyElem(var X, Y: tape;

var Buf: elem; var E: boolean);

{ копирование элемента и считывание следующего

{ в Buf с проверкой конца серии (E=True) }

if not Eof(X) then Read(X, Buf)

else Buf.Key:=-1; { барьер: достигнут конец файла }

E:=(Buf.Key

Procedure CopySer(var X, Y: tape; var Buf: elem);

{ копирование серии из X в Y }

{в начале Buf-первый элемент текущей серии на X }

{в конце Buf-первый элемент следующей или –1 (конец X) }

if Buf.Key>0 then { файл X не считан }

CopyElem(X, Y, Buf, E)

Until E { E=True в конце серии }

Procedure Raspred;

{ распределение A ---> B и C }

Read(A, S); { первый элемент из A }

Rewrite(B); Rewrite(C);

CopySer(A, B, S); {S-первый элемент следующей серии }

if S.Key>0 then { файл A скопирован не весь }

CopySer(A, C, S)

Until S.Key<0

Procedure Slian;

{ слияние B и C--->A }

E1, E2: boolean;

Procedure SlianSer;

{ слияние серий из B и C ---> A }

{ S и T - первые элементы серий }

{ S.Key<0-весь файл B считан, T.Key<0-файл C считан }

E1:=False; E2:=False;

if (S.Key>0) and ((S.Key

{ файл B не считан и текущий элемент B меньше, чем в C либо файл C полностью считан }

CopyElem(B, A, S, E1);

if E1 then { достигнут конец серии на B }

CopySer(C, A, T)

CopyElem(C, A, T, E2);

if E2 then { достигнут конец серии на C }

CopySer(B, A, S)

Begin { начало Slian }

if not (Eof(B) or Eof(C)) then

begin { оба файла не пусты }

L:=0; { счетчик числа серий }

While (S.Key>0) or (T.Key>0) do

Begin { начало основной программы }

Write("Введите имя файла для записи элементов: ");

Assign(A, Name);

Assign(B, "Rab1");

Assign(C, "Rab2");

L:=0; { L - число серий после слияния - параметр }

WriteLn("Файл A: "); Pech(A);

Raspred; { фаза распределения }

WriteLn("Файл B: "); Pech(B);

WriteLn("Файл C: "); Pech(C);

ReadLn; { пауза }

Slian { фаза слияния }

Until L<=1; { L=0, если исходный файл отсортирован }

WriteLn("Файл A в конце: ");

Close(B); Erase(B); { удаление рабочих файлов }

Close(C); Erase(C);

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

Эффективность сортировки можно повысить, используя многопутевое слияние, в котором распределение выполняется на k лент. Поскольку число серий на каждом проходе уменьшается в k раз, количество пересылок M пропорционально величине n log k n. Если общее число лент четное, то можно использовать однофазный метод слияния, распределяя серии с одной половины лент на другую. Платой за повышение эффективности многопутевого слияния являются, как всегда, увеличение сложности реализации и дополнительные затраты внешней памяти.

На сколько может отличаться количество серий после разделения? На первый взгляд кажется, что не более, чем на одну, но это не так. Например, при распределении серий 17, 25, 41, ’ 9, 60, ‘ 50, 52, ‘ 7 первая и третья серии сливаются в общую серию, что не происходит со второй и четвертой сериями. В результате при последующем слиянии серии на одной из лент могут закончиться раньше, и придется впустую переписывать остаток другой ленты, теряя эффективность. Подобные ситуации учитываются в методе многофазной сортировки. Рассмотрим его на примере трех лент.

Пусть при соединении лент B и C на ленту A серии на B заканчиваются раньше. Тогда лента B объявляется выходной, а лента A становится входной. Процесс продолжается до нового повторения ситуации, когда серии на одной из входных лент заканчиваются. Многофазная сортировка возможна и при многопутевом слиянии. Например, при использовании в сортировке k лент можно постоянно иметь одну выходную ленту. При исчерпании серий на одной из k-1 входных лент эта лента становится выходной вместо предыдущей выходной ленты.

Методы внутренней и внешней сортировок могут использоваться совместно. Пусть сортируется большой по объему файл. В оперативной памяти выделяется буфер максимально возможного размера. Файл делится на блоки, соответствующие величине буфера. Блоки читаются в буфер, сортируются одним из методов внутренней сортировки и переписываются в другой файл. Сейчас каждый блок нового файла является серией достаточно большой длины, определяемой размером буфера. Остается применить один из методов внешней сортировки, использующий данные серии.



Рекомендуем почитать

Наверх