- •Оглавление
- •Введение
- •Раздел 1. Основные структуры данных
- •Тема 1. Введение в структуры данных. Динамическое распределение памяти
- •Классификация структур данных
- •1.2. Переменные-указатели и динамическое распределение памяти.
- •Например, указатели на простейшие базовые типы вводятся следующим образом:
- •Var pStr1,pStr2 :TpString; {переменные-указатели на строки}
- •1.3. Дополнительные вопросы использования переменных-указателей
- •1.4. Контрольные вопросы по теме
- •Тема 2. Структуры данных “стек” и “очередь”
- •2.1. Что такое стек и очередь?
- •2.2. Статическая реализация стека
- •2.3. Динамическая реализация стека
- •{Ссылочный тип для адресации элементов стека}
- •2.4. Статическая реализация очереди
- •2.5. Динамическая реализация очереди
- •{Ссылочный тип для адресации элементов очереди}
- •2.6. Практические задания
- •2.7. Контрольные вопросы по теме
- •Тема 3. Основы реализации списковых структур
- •3.1. Структуры данных типа “линейный список”
- •3.2. Первый способ статической реализации списка.
- •3.3. Второй способ статической реализации списка.
- •3.4. Управление памятью при статической реализации списков
- •3.5. Динамическая реализация линейных списков
- •3.6. Практические задания
- •3.7. Контрольные вопросы по теме
- •Тема 4. Усложненные списковые структуры
- •4.1. Двунаправленные линейные списки
- •4.2. Комбинированные структуры данных: массивы и списки указателей
- •4.3. Комбинированные структуры данных: массивы и списки списков
- •4.4. Практические задания.
- •4.5. Контрольные вопросы по теме
- •Тема 5. Основные понятия о древовидных структурах
- •5.1. Основные определения
- •5.2. Двоичные деревья
- •5.3. Идеально сбалансированные деревья
- •5.4. Практические здания
- •5.5. Контрольные вопросы по теме
- •Тема 6. Реализация поисковых деревьев
- •Двоичные деревья поиска.
- •6.2. Добавление вершины в дерево поиска
- •6.3. Удаление вершины из дерева поиска
- •6.4. Практические задания
- •Контрольные вопросы по теме
- •Тема 7. Дополнительные вопросы обработки деревьев. Графы.
- •Проблемы использования деревьев поиска
- •7.2. Двоичные деревья с дополнительными указателями
- •7.3. Деревья общего вида (не двоичные).
- •Представление графов
- •Практические задания
- •Контрольные вопросы по теме
- •Раздел 2. Алгоритмы сортировки и поиска
- •Тема 1. Классификация методов. Простейшие методы сортировки
- •1.1. Задача оценки и выбора алгоритмов
- •1.2. Классификация задач сортировки и поиска
- •1.3. Простейшие методы сортировки: метод обмена
- •1.4. Простейшие методы сортировки: метод вставок
- •1.5. Простейшие методы сортировки: метод выбора
- •1.6. Практическое задание
- •1.7. Контрольные вопросы по теме
- •Тема 2. Улучшенные методы сортировки массивов
- •2.1. Метод Шелла
- •2.2. Метод быстрой сортировки
- •2.3. Пирамидальная сортировка
- •2.4. Практическое задание
- •2.5. Контрольные вопросы по теме
- •Тема 3. Специальные методы сортировки
- •3.1. Простейшая карманная сортировка.
- •3.2. Карманная сортировка для случая повторяющихся ключей
- •3.3. Поразрядная сортировка
- •3.4. Практическое задание
- •3.5. Контрольные вопросы по теме
- •Тема 4. Поиск с использованием хеш-функций
- •4.1. Основные понятия
- •4.2. Разрешение конфликтов: открытое хеширование
- •4.3. Разрешение конфликтов: внутреннее хеширование
- •4.4. Практические задания
- •4.5. Контрольные вопросы по теме
- •Тема 5. Внешний поиск и внешняя сортировка
- •5.1. Особенности обработки больших наборов данных
- •5.2. Организация внешнего поиска с помощью б-деревьев.
- •5.4. Поиск элемента в б-дереве.
- •5.5. Добавление вершины в б-дерево
- •5.6. Удаление вершины из б-дерева
- •5.7. Внешняя сортировка
- •5.8. Практические задания
- •5.9. Контрольные вопросы по теме
- •Основные термины и понятия
- •Литература
Тема 3. Специальные методы сортировки
3.1. Простейшая карманная сортировка.
Как было отмечено ранее, специальные методы сортировки основаны либо на использовании некоторой дополнительной информации об исходном наборе данных, либо на использовании дополнительной памяти, сопоставимой по объему с самим сортируемым массивом. Отсюда следует, что они имеют ограниченную область применения, но их огромное преимущество – более высокая эффективность, оцениваемая как O(n).
Самая простая разновидность специальных методов – так называемая карманная сортировка.
Пусть как обычно исходный набор данных включает n элементов, причем относительно их ключей известно следующее:
ключи являются целыми числами, изменяющимися только от 1 до n
все эти ключи различные
В этом случае ключи можно рассматривать как индексы элементов в массиве. Если в исходном массиве значение ключа может НЕ совпадать с индексом элемента, то после сортировки соответствие должно быть полным: ключ 1 – в ячейке 1, ключ 2 - в ячейке 2 и т.д., ключ n – в ячейке n.
Для реализации метода в простейшем случае можно ввести второй массив для хранения отсортированного набора. Тогда сортировка сводится к последовательному просмотру элементов исходного массива и копированию каждого элемента на его нужное место в результирующем массиве.
Например, для массива из 10 элементов с неповторяющимися ключами от 1 до 10 получим:
4 2 5 7 1 8 3 10 6 9
1 2 3 4 5 6 7 8 9 10
Вся сортировка сводится лишь к 10 пересылкам и не требует ни одного сравнения! Реализация - одним единственным циклом (здесь Mas – исходный массив, RezMas - результирующий):
for i := 1 to n do
RezMas[Mas[i].key] := Mas[i];
Если есть проблемы со свободной памятью, то метод можно изменить так, чтобы не использовать дополнительный массив, а проводить сортировку “на месте”, правда – за счет небольшого увеличения числа операций. Алгоритм состоит в повторении следующих шагов:
берем первый элемент в исходном массиве, пусть его ключ равен i
перемещаем в массиве первый элемент в ячейку i, а i-ый элемент – в первую ячейку; после этой операции i-ый элемент окажется на своем месте
если ключ первого элемента не равен 1 (например – j ), то обмениваем его с j-ым элементом, после чего и j-ый элемент оказывается на своем месте
повторяем эти действия до тех пор, пока на первом месте не окажется элемент с ключом 1, причем каждое повторение обязательно размещает один элемент массива на своем “законном” месте
при необходимости повторяем эти действия и для других элементов массива
Пример работы алгоритма – в следующей таблице.
4 |
2 |
5 |
7 |
1 |
8 |
3 |
10 |
6 |
9 |
1.key= 4, меняем элементы 4 и 1 |
7 |
2 |
5 |
4 |
1 |
8 |
3 |
10 |
6 |
9 |
1.key= 7, меняем элементы 7 и 1 |
3 |
2 |
5 |
4 |
1 |
8 |
7 |
10 |
6 |
9 |
1.key= 3, меняем элементы 3 и 1 |
5 |
2 |
3 |
4 |
1 |
8 |
7 |
10 |
6 |
9 |
1.key= 5, меняем элементы 5 и 1 |
1 |
2 |
3 |
4 |
5 |
8 |
7 |
10 |
6 |
9 |
1.key= 1, также для 2, 3, 4, 5; 6.key= 8, обмен 6 и 8 |
1 |
2 |
3 |
4 |
5 |
10 |
7 |
8 |
6 |
9 |
6.key= 10, меняем 6 и 10 |
1 |
2 |
3 |
4 |
5 |
9 |
7 |
8 |
6 |
10 |
6.key= 9, меняем 6 и 9 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
6.key= 6, также для остальных; все готово |
В этом примере потребовалось 17 сравнений и 7 пересылок. В общем случае, трудоемкость метода пропорциональна n.
Схема программной реализации:
for i := 1 to n do
while Mas[i]. key <> i do
“переставить Mas[i] и Mas[Mas[i].key]”;