- •Ответы на экзаменационные вопросы по курсу «Алгоритмы и структуры данных»
- •1.Понятие типов и структур данных. Оперативные и внешние структуры.
- •2.Стандартные и пользовательские типы данных.
- •3.Определение и представление структур данных.
- •4.Классификация структур данных. Векторы и массивы как статистические структуры. Классификация структур данных
- •Статические структуры данных Векторы
- •Массивы
- •5.Записи и таблицы как статические структуры. Записи
- •6.Понятие списковой структуры. Стек как полустатическая структура. Операция над стеками
- •Алгоритмы основных операций со стеком
- •7.Очередь как полустатическая структура. Операции над очередью. Очередь
- •8.Недостатки полустатической очереди, методы их исправления. Очередь со сдвигом.
- •9.Кольцевая полустатическая очередь. Операции над кольцевой очередью. Деки, операции над ними.
- •10.Понятие динамических структур данных. Организация односвязных и двусвязных списков. Простейшие операции над односвязными списками. Динамические структуры данных
- •Связные списки
- •Односвязные списки
- •Кольцевой односвязный список
- •Двусвязный список
- •Кольцевой двусвязный список
- •Простейшие операции над односвязными списками
- •11.Реализация стеков с помощью списков.
- •Утилизация освободившихся элементов в многосвязных списках
- •13.Очередь и операции над ней при реализации связными списками
- •14.Операции вставки и извлечения элементов из списка. Сравнение этих операций с аналогичными в массивах. Недостаток связного списка по сравнению с массивом.
- •15.Пример алгоритма решения задачи извлечения элементов из списка по заданному признаку.
- •16.Пример алгоритма решения задачи вставки заданного элемента в упорядоченный список.
- •17.Элементы заголовков в списках; нелинейные связные структуры.
- •Нелинейные связанные структуры
- •18.Понятие рекурсивных структур данных. Деревья, их признаки и представления.
- •Деревья
- •Бинарные деревья
- •19.Алгоритм сведения m-арного дерева к бинарному; основные операции над деревьями; виды обхода.
- •Графическое пояснение алгоритма
- •Основные операции с деревьями
- •Рекурсивные алгоритмы обхода (прохождения) бинарных деревьев
- •20.Понятие поиска и ключей; назначение и структуры алгоритмов поиска.
- •21.Последовательный поиск и его эффективность.
- •22.Индексно-последовательный поиск.
- •23.Оптимизация поиска. Переупорядочивание таблицы с учетом вероятности поиска элемента. Дерево оптимального поиска.
- •24.Метод оптимизации поиска путем перестановки в начало списка.
- •25.Метод транспозиции при оптимизации поиска.
- •26.Бинарный поиск
- •27.Алгоритм создания упорядоченного бинарного дерева.
- •28.Поиск по бинарному дереву. Эффективность поиска по бинарному дереву.
- •29.Поиск по бинарному дереву с включением.
- •30.Поиск по бинарному дереву с удалением.
- •31.Алгоритмы прохождения бинарных деревьев. Рекурсивные алгоритмы обхода (прохождения) бинарных деревьев
- •32.Понятие сортировки, ее эффективность; классификация методов сортировки.
- •33.Сортировка методом прямого выбора.
- •34.Сортировка методом прямого включения. Сортировка методом прямого включения
- •Эффективность алгоритма прямого включения
- •35.Сортировка методом прямого обмена.
- •36.Быстрая сортировка.
- •37.Сортировка Шелла.
- •38.Сортировка с помощью бинарного дерева.
- •39.Сравнительный анализ эффективности методов сортировки.
- •40.Нерекурсивный алгоритм обхода бинарного дерева.
38.Сортировка с помощью бинарного дерева.
Двоичным деревом назовем упорядоченную структуру данных, в которой каждому элементу -- предшественнику или корню (под)дерева -- поставлены в соответствие по крайней мере два других элемента (преемника). Причем для каждого предшественника выполнено следующее правило: левый преемник всегда меньше, а правый преемник всегда больше или равен предшественнику. Если мы составим такое дерево из букв слова "СОРТИР", сравнивая ASCII коды букв, то получим следующую структуру:
С
/ \
О Т
/ \
И Р
Как видно, узел "С" имеет два преемника: левый "О" и правый "Т". Если составить бинарное дерево из элементов неупорядоченного массива, то в общем случае дерево получится достаточно хорошо заполненным (а если массив уже был рассортирован, то дерево выродится в линейный список). Если мы будем обходить дерево по правилу "ЛЕВЫЙ преемник - КОРЕНЬ - ПРАВЫЙ преемник", то, записывая все встречающиеся элементы в массив, мы получим упорядоченное в порядке возрастания множество. На этом и основана идея сортировки деревом.
Использование такой сортировки удобно тогда, когда удобно представлять данные в виде дерева.
Недостаток метода - требуется много памяти. В приведеном примере - дополнительный мегабайт данных на каждые 256k элементов.
/*********** сортировка с помощью двоичного дерева *************/
typedef struct tree
{
int a; // данные
struct tree *left; // левый преемник
struct tree *right; // правый преемник
} TREE;
TREE *add_to_tree(TREE *root, int new_value)
{
if (root==NULL) // если дошли до корня - создаем новый элемент
{
root = (TREE*)malloc(sizeof(TREE));
root->a = new_value;
root->left = root->right = 0;
return root;
}
if less(root->a, new_value) // добавлем ветвь
root->right = add_to_tree(root->right, new_value);
else
root->left = add_to_tree(root->left, new_value);
return root;
}
void tree_to_array(TREE *root, int a[]) // процедура заполнения массива
{
static max2=0; // счетчик элементов нового массива
if (root==NULL) return; // условие окончания - найден корень
tree_to_array(root->left, a); // обход левого поддерева
a[max2++] = root->a;
tree_to_array(root->right, a); // обход правого поддерева
free(root);
}
void sort_tree(int a[], int max) // собственно сортировка
{
TREE *root = 0;
for (int i=0; i<max; i++) // проход массива и заполнение дерева
root = add_to_tree(root, a[i]);
tree_to_array(root, a); // заполнение массива
}
39.Сравнительный анализ эффективности методов сортировки.
Для
проведения исследования были выбраны
следующие алгоритмы сортировки:
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 миллисекунды меньше.
Однако при сортировке частично
отсортированного массива быстрая
сортировка срабатывает намного быстрее
и потребляет меньшее количество памяти.
