
- •Функции ос, интерфейс пользователя.
- •Интерфейс пользователя
- •Интерфейс командной строки
- •Файловая структура. Диски, файлы, их имена.
- •Каталоги
- •Основные понятия
- •Работа с файлами
- •Работа с каталогами
- •Командная строка
- •Типы данных в Turbo Pascal. Порядковый, вещественный, структурированный. Совместимость и преобразование типов. Типы данных
- •Простые типы данных
- •Имена и доступ к файлам в Turbo Pascal.
- •Доступ к файлам.
- •Процедуры и функции для работы с файлами
- •Текстовые файлы
- •Типизированные файлы
- •Нетипизированные файлы
- •Операторы вводы/ вывода в Turbo Pascal.
- •Операции в Turbo Pascal. Математические операции
- •Логические операции
- •Операции отношения
- •Приоритет операций
- •Условный оператор. Оператор выбора в Turbo Pascal.
- •Метки и оператор перехода.
- •Операторы циклов с предусловием, постусловием и с параметром в Turbo Pascal.
- •Арифметические циклы (циклы с параметром)
- •Итерационные циклы с предусловием
- •Итерационные циклы с постусловием
- •Операторы завершения цикла
- •Процедуры и функции в Turbo Pascal. Локализация переменных. Формальные и фактические параметры в Turbo Pascal. Процедуры и функции
- •Описание и вызов процедур и функций
- •Локальные и глобальные переменные в Turbo Pascal.
- •Переход в графический режим в Turbo Pascal. Масштабирование экрана. Процедуры и функции для работы с экраном в графическом режиме.
- •Понятие алгоритма и его свойства. Линейные, разветвляющиеся, циклические алгоритмы.
- •Алгоритмы поиска элементов из массивов данных. Двоичный (бинарный) поиск элемента в массиве
- •Интерполяционный поиск элемента в массиве
- •Алгоритмы выборки элементов из массивов данных. Алгоритмы сортировки данных.
- •Критерии Эффективности
- •Сортировка выбором
- •Сортировка пузырьком
- •Сортировка простыми вставками
- •Сортировка Шелла.
- •Сортировка быстрая
- •Сортировка поразрядная
Сортировка поразрядная
Пусть имеем максимум по k байт в каждом ключе (хотя за элемент сортировки вполне можно принять и что-либо другое, например слово - двойной байт, или буквы, если сортируются строки). k должно быть известно заранее, до сортировки.
Разрядность данных (количество возможных значений элементов) - m - также должна быть известна заранее и постоянна. Если мы сортируем слова, то элемент сортировки - буква, m = 33. Если в самом длинном слове 10 букв, k = 10. Обычно мы будем сортировать данные по ключам из k байт, m=256.
Пусть у нас есть массив source из n элементов по одному байту в каждом.
Для примера можете выписать на листочек массив source = <7, 9, 8, 5, 4, 7, 7>, и проделать с ним все операции, имея в виду m=9.
Составим таблицу распределения. В ней будет m (256) значений и заполняться она будет так:
for i := 0 to Pred(255) Do distr[i]:=0;
for i := 0 to Pred(n) Do distr[source[i]] := distr[[i]] + 1;
Для нашего примера будем иметь distr = <0, 0, 0, 0, 1, 1, 0, 3, 1, 1>, то есть i-ый элемент distr[] - количество ключей со значением i.
Заполним таблицу индексов:
index: array[0 .. 255] of integer;
index[0]:=0;
for i := 1 to Pred(255) Do index[i]=index[i-1]+distr[i-1];
В index[ i ] мы поместили информацию о будущем количестве символов в отсортированном массиве до символа с ключом i.
Hапример, index[8] = 5 : имеем <4, 5, 7, 7, 7, 8>.
А теперь заполняем новосозданный массив sorted размера n:
for i := 0 to Pred(n) Do Begin
sorted[ index[ source[i] ] ]:=source[i];
{
попутно изменяем index уже вставленных символов, чтобы
одинаковые ключи шли один за другим:
}
index[ source[i] ] := index[ source[i] ] +1;
End;
Итак, мы научились за O(n) сортировать байты. А от байтов до строк и чисел - 1 шаг. Пусть у нас в каждом числе - k байт.
Будем действовать в десятичной системе и сортировать обычные числа ( m = 10 ).
сначала они в сортируем по младшему на один беспорядке: разряду: выше: и еще раз:
523 523 523 088
153 153 235 153
088 554 153 235
554 235 554 523
235 088 088 554
Hу вот мы и отсортировали за O(k*n) шагов. Если количество возможных различных ключей ненамного превышает общее их число, то 'поразрядная сортировка' оказывается гораздо быстрее даже 'быстрой сортировки'!
Пример:
Const
n = 8;
Type
arrType = Array[0 .. Pred(n)] Of Byte;
Const
m = 256;
a: arrType =
(44, 55, 12, 42, 94, 18, 6, 67);
Procedure RadixSort(Var source, sorted: arrType);
Type
indexType = Array[0 .. Pred(m)] Of Byte;
Var
distr, index: indexType;
i: integer;
begin
fillchar(distr, sizeof(distr), 0);
for i := 0 to Pred(n) do
inc(distr[source[i]]);
index[0] := 0;
for i := 1 to Pred(m) do
index[i] := index[Pred(i)] + distr[Pred(i)];
for i := 0 to Pred(n) do
begin
sorted[ index[source[i]] ] := source[i];
index[source[i]] := index[source[i]]+1;
end;
end;
var
b: arrType;
begin
RadixSort(a, b);
end.
Сортировка подсчетом
Пусть у нас есть массив source из n десятичных цифр ( m = 10 ). Например, source[7] = { 7, 9, 8, 5, 4, 7, 7 }, n=7. Здесь положим const k=1.
Создать массив count из m элементов(счетчиков).
Присвоить count[i] количество элементов source, равных i. Для этого:
проинициализовать count[] нулями,
пройти по source от начала до конца, для каждого числа увеличивая элемент count с соответствующим номером.
for( i=0; i<n; i++) count [ source[i] ]++
В нашем примере count[] = { 0, 0, 0, 0, 1, 1, 0, 3, 1, 1 }
Присвоить count[i] значение, равное сумме всех элементов до данного: count[i] = count[0]+count[1]+...count[i-1]. В нашем примере count[] = { 0, 0, 0, 0, 1, 2, 2, 2, 5, 6 } Эта сумма является количеством чисел исходного массива, меньших i.
Произвести окончательную расстановку.
Для каждого числа source[i] мы знаем, сколько чисел меньше него - это значение хранится в count[ source[i] ]. Таким образом, нам известно окончательное место числа в упорядоченном массиве: если есть K чисел меньше данного, то оно должно стоять на на позиции K+1. Осуществляем проход по массиву source слева направо, одновременно заполняя выходной массив dest:
for ( i=0; i<n; i++ ) {
c = source[i];
dest[ count[c] ] = c;
count[c]++; // для повторяющихся чисел
}
Таким образом, число c=source[i] ставится на место count[c]. На этот случай, если числа повторяются в массиве, предусмотрен оператор count[c]++, который увеличивает значение позиции для следующего числа c, если таковое будет.
Циклы занимают (n + m) времени. Столько же требуется памяти.
Итак, мы научились за (n + m) сортировать цифры. А от цифр до строк и чисел - 1 шаг. Пусть у нас в каждом ключе k цифр ( m = 10 ). Аналогично случаю со списками отсортируем их в несколько проходов от младшего разряда к старшему.
Общее количество операций, таким образом, ( k(n+m) ), при используемой дополнительно памяти (n+m). Эта схема допускает небольшую оптимизацию. Заметим, что сортировка по каждому байту состоит из 2 проходов по всему массиву: на первом шаге и на четвертом. Однако, можно создать сразу все массивы count[] (по одному на каждую позицию) за один проход. Неважно, как расположены числа - счетчики не меняются, поэтому это изменение корректно. Таким образом, первый шаг будет выполняться один раз за всю сортировку, а значит, общее количество проходов изменится с 2k на k+1.