- •1. Cтруктуры данных и алгоритмы
- •1.1. Понятие структур данных и алгоритмов
- •1.2. Информация и ее представление в памяти
- •1.3. Классификация структур данных
- •1.4. Операции над структурами данных
- •1.5. Структурность данных и технология программирования
- •2. Простые структуры данных
- •2.1. Числовые типы
- •2.1.1. Целые типы
- •2.1.2. Вещественные типы
- •1). Десятичное число 15.375;
- •2). Десятичное число -0.5;
- •3). Десятичное число -25.75;
- •4). Число 0.0;
- •5). Числа верхней и нижней границ положительного диапазона
- •2.1.3. Операции над числовыми типами
- •2.2. Битовые типы
- •2.3. Логический тип
- •2.4. Символьный тип
- •2.5. Перечислимый тип
- •2.6. Интервальный тип
- •2.7. Указатели
- •2.7.1. Физическая структура указателя
- •2.7.2. Представление указателей в языках программирования
- •2.7.3. Операции над указателями.
- •3. Статические структуры данных
- •3.1. Векторы
- •3.2. Массивы
- •3.2.1. Логическая структура
- •3.2.2. Физическая структура
- •3.2.3. Операции
- •3.3 Множества
- •3.3.1 Множества и математика
- •3.3.1.1 Способы задания множеств
- •3.3.1.2 Операции над множествами
- •3.3.1.3 Множественный тип и его свойства
- •3.3.1.4 Переменные и константы множественных типов
- •3.3.1.5. Выражения множественного типа
- •3.3.2. Представление множеств в памяти эвм
- •3.3.2.1. Числовые множества
- •3.3.2.2. Символьные множества
- •3.3.2.3. Множество из элементов перечислимого типа
- •3.3.2.4. Множество от интервального типа
- •3.3.2.5. Операции над множествами
- •3.4. Записи
- •3.4.1. Логическое и машинное представление записей
- •3.4.2. Операции над записями
- •3.5. Таблицы
- •3.6.2. О сложности алгоритмов
- •3.6.3. Сортировка подсчетом
- •3.6.4. Сортировка включением
- •3.6.4.1. Простое включение
- •3.6.4.2.Метод Шелла (модифицированный)
- •3.6.5. Сортировка извлечением
- •3.6.5.1.Простое извлечение
- •3.6.5.2.Древесная сортировка(модифицированный)
- •3.6.6. Сортировка обменами
- •3.6.6.1. Пузырьковая сортировка
- •3.6.6.2. Быстрая сортировка (Хоара) (модифицированный)
- •3.6.7. Сортировка слиянием
- •3.6.8. Сортировка распределением
- •3.6.8.1. Вырожденное распределение
- •3.6.8.2. Сортировка распределением
- •3.6.9. Сравнительный анализ
- •3.7. Операции логического уровня над статическими структурами. Поиск
- •3.7.1. Линейный (последовательный) поиск
- •3.7.2. Быстрый последовательный список
- •3.7.3. Дихотомический (бинарный) поиск
- •3.7.4. Интерполяционный поиск
3.6.3. Сортировка подсчетом
Суть метода заключается в том, что на каждом шаге мы подсчитываем, в какую позицию результирующего массива надо записать очередной элемент исходного массива. Выглядит это так:
fori := 1 toNdo
begin
<вычислить_место_k+1_элемента_A[i]
в_результирующем_массиве_B>
B[k+1] := A[i];
end;
Слева от B[k+1] должны стоять элементы большие или равные B[k+1]. Значит число k складывается из количества элементов меньших A[i] и, возможно, некоторого числа элементов, равных A[i]. Условимся, что из равных мы будем учитывать только те элементы, которые в исходном массиве стоят левее A[i]. Теперь вычисление k можно записать следующим образом:
k := 0;
forj := 1 toNdo
if (A[i]>A[j])or((A[i]=A[j])and(i>j)) then
Inc(k);
Легко видеть, что этот алгоритм всегда имеет сложности T(n2) (два вложенных цикла, зависящих от n линейно) и O(n) (результирующий массив).
3.6.4. Сортировка включением
В этой сортировке массив делится на 2 части: отсортированную и неотсортированную. На каждом шаге берется очередной элемент из неотсортированной части и «включается» в отсортированную часть массива.
3.6.4.1. Простое включение
Пусть отсортировано начало массива A[1], A[2], ..., A[i-1], а остаток массива A[i], ...,A[n] содержит неотсортированную часть. На очередном шаге будем включать элемент A[i] в отсортированную часть, ставя его на соответствующее место. При этом придется сдвинуть часть элементов, больших A[i], (если таковые есть) на одну позицию правее, чтобы освободить место для элемента A[i]. Но при сдвиге будет потеряно само значение A[i], поскольку в эту позицию запишется первый (самый правый - с самым большим индексом) сдвигаемый элемент. Поэтому прежде чем производить сдвиг элементов необходимо сохранить значение A[i] в промежуточной переменной.
Так как массив из одного элемента можно считать отсортированным, начнем с i=2.
Программа будет выглядеть так:
fori := 2 tondo
begin
Tmp := A[i];
j := i-1;
while (A[j]>Tmp)and(j>1) do
begin
A[j+1] := A[j];
Dec(j)
end;
A[j+1] := Tmp;
end;
Этот алгоритм также имеет максимальную и среднюю сложности T(n2), но в случае исходно отсортированного массива внутренний цикл не будет выполняться ни разу, поэтому метод имеет Tmin(n). Можно заметить, что метод использует любой частичный порядок, и чем в большей степени массив исходно упорядочен, тем быстрее он закончит работу. В отличие от предыдущего метода, этот не требует дополнительной памяти.
3.6.4.2.Метод Шелла (модифицированный)
Метод Шелла является усовершенствованием простого включения, которое основано на том, что включение использует любой частичный порядок. Но недостатком простого включения является то, что во внутреннем цикле элемент A[i] фактически сдвигается на одну позицию. И так до тех пор, пока он не достигнет своего места в отсортированной части. (На самом деле мы избавлялись от сдвига A[i], сохраняя его в промежуточной переменной, но сути метода это не изменяло, так как передвигалось место, оставленное под сохраненное значение). Метод Шелла позволяет преодолеть это ограничение следующим интересным способом.
Вместо включения A[i] в подмассив предшествующих ему элементов, его включают в подсписок, содержащий элементы A[i-h], A[i-2h], A[i-3h] и так далее, где h - положительная константа. Таким образом формируется массив, в котором «h- серии» элементов, отстоящих друг от друга на h, сортируются отдельно.
Конечно, этого недостаточно: процесс возобновляется с новым значением h, меньшим предыдущего. И так до тех пор, пока не будет достигнуто значение h=1.
В настоящее время неизвестна последовательность hi, hi-1, hi-2, ..., h1, оптимальность которой доказана. Для достаточно больших массивов рекомендуемой считается такая последовательность, что hi+1=3hi+1, а h1=1. Начинается процесс с hm-2, где m - наименьшее целое такое, что hmn. Другими словами hm-2 первый такой член последовательности, что hm-2[n/9].
Теперьзапишемалгоритм:
Step := 1;
while Step < N div 9 do Step := Step*3 + 1;
Repeat
for k := 1 to Step do
begin
i := Step + k;
while i <= N do
begin
x := A^[i];
j := i - Step;
while (j >= 1) and (A^[j]>x) do
begin
A^[j + Step] := A^[j];
Dec(j);
end;
A^[j + Step] := x;
Inc(i, Step);
end;
end;
Step := Step div 3;
until Step=0;
Как показывают теоретические выкладки, которые мы приводить не будем, сортировке методом Шелла требуется в среднем 1,66n1,25 перемещений.
