Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Отладка программных решений. Учебно-методическое пособие для студентов направлений подготовки бакалавриата 09.03.03 «Прикладная информатика», 09.03.04

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
41
Задача поиска наибольшей увеличивающейся
подпоследовательности.
Задача о редакционном расстоянии (расстояние Левенштейна). Задача о вычислении чисел Фибоначчи Задача о порядке перемножения матриц. Задача о выборе траектории Задача последовательного принятия решения Задача об использовании рабочей силы
Последнее, что будет рассмотрено – это графы. Граф – это особая структура данных, которая определяется исходной задачей, а не алгоритмом. У графа имеются вершины (узлы) и ребра, которые эти вершины соединяют. Вершины, как правило, несут какую-то информацию. Каждое ребро ограничивается двумя вершинами, находящимися на его концах. У ребра можно задать направление, которое ограничит переход между вершинами только одним направлением. Такой граф будет называться направленным. Также ребру может быть присвоен вес. Вес представляет физическое расстояние между двумя вершинами, время перехода от вершины к вершине или затраты на такой переход. Граф, у которого ребра имеют вес называется взвешенным. Если от любой вершины графа можно добраться до любой другой вершины графа, то такой граф называется связанным.
Для работы с графом в программировании используют либо матрицу смежности, либо список смежности. Обе этих структуры нацелены на то, чтобы обозначить смежные вершины, вершины, которые соединены ребрами.
Матрица смежности представляет собой двумерный массив, элементы которого обозначают наличие связи между двумя вершинами. Например, если граф содержит N вершин, то матрица смежности представляет собой массив из N строк и N столбцов. Заголовками как строк, так и столбцов будут метки вершин графа. Элемент матрицы на пересечении строки и столбца будет иметь значение 1 (если вершины связаны) или 0 (если вершины не связаны). У такого
42
представления графа есть недостаток – значения матрицы над главной диагональю зеркально отражаются значениями под главной диагональю. Соответственно, при добавлении связи между вершинами в граф, в матрице смежности потребуется изменить два элемента вместо одного.
Другим способом представления графа является список смежности, который является массивом списков (или списком списков). Каждый элемент списка/массива является вершиной графа и содержит массив/список с информацией о том, какие вершины являются смежными по отношению к нему.
Одной из основных операций, выполняемых над графами, является определение всех вершин, достижимых от заданной вершины. Существует два основных способа выполнение такой операции:
обход в глубину обход в ширину.
Результатом работы любого из этих способов будет перебор всех соединенных вершин. Для реализации обход в глубину используется структура данных – стек. Для реализации обход в ширину используется структура данных – очередь. Алгоритм обхода в глубину сохраняет в стеке информацию о последовательном переходе от вершины к вершине (движение идет от исходной вершины, как бы «вглубь»). И, если достигнут конец, то возвращение (подъем) обратно, к исходной вершине. При обходе в ширину, напротив, алгоритм посещает все вершины, смежные с исходной, и только после этого уходит «глубже».
Общее задание
1. Требуется сделать desktop-приложение по реализации
алгоритмов. Необходимо реализовать следующее:
а. На форме разместить 3 панели (по количеству заданий,
одна панель под одно задание).
43
б. В первой панели выводить описание абстрактного типа
данных по заданию, а также расположить кнопки для
добавления в тип значения (добавляется случайное число),
извлечения (удаления) из типа значения, а также вывода всех значений в типе.
в. Во второй панели выводить описание алгоритма
сортировки, исходный, сгенерированный массив, и кнопку для пошаговой демонстрации работы алгоритма.
г. В третьей панели выводить описание алгоритма и пример
его работы.
д. Обязательно! Программа должна корректно
отрабатывать случаи недостаточности данных для выполнения задания.
е. Каждое задание разбито на 3 части по уровню сложности:
первые 4 задачи на «3», следующие 4 задачи на «4» и
последние 4 задачи на «5». Студент сам выбирает
сложность задачи (но, номер конкретной задачи будет
выдавать преподаватель). Оценка студента по этой
работе будет складываться как среднеарифметическое по каждому заданию.
Задание 1. Структуры данных.
1. Реализовать абстрактный тип данных стек на основе структуры данных
массив.
2. Реализовать абстрактный тип данных очередь на основе структуры
данных массив.
3. Реализовать абстрактный тип данных дек на основе структуры данных
массив.
4. Реализовать абстрактный тип данных циклический список на основе
структуры данных массив.
44
======================================================
5. Реализовать абстрактный тип данных стек на основе структуры данных
односвязный список.
6. Реализовать абстрактный тип данных очередь на основе структуры
данных односвязный список.
7. Реализовать абстрактный тип данных дек на основе структуры данных
односвязный список.
8. Реализовать абстрактный тип данных циклический список на основе
структуры данных односвязный список.
======================================================
9. Реализовать абстрактный тип данных стек на основе структуры данных
двусвязный список.
10. Реализовать абстрактный тип данных очередь на основе структуры
данных двусвязный список.
11. Реализовать абстрактный тип данных дек на основе структуры данных
двусвязный список.
12. Реализовать абстрактный тип данных циклический список на основе
структуры данных двусвязный список.
Задание 2. Сортировка.
1. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
– сортировка пузырьковая.
2. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
– сортировка перемешиванием.
3. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
– сортировка вставками.
4. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
– сортировка выбором.
======================================================
45
5. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
сортировка слиянием.
6. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
сортировка Шелла.
7. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
сортировка быстрая.
8. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
сортировка Timsort.
======================================================
9. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
Пирамидальная сортировка.
10. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
Плавная сортировка.
11. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
Придурковатая сортировка.
12. Реализовать алгоритм сортировки для одномерного массива. Алгоритм
Интроспективная сортировка.
Задание 3. Алгоритмы
1. Реализовать задачу о размене монет, используя жадный алгоритм.
2. Реализовать задачу о рюкзаке, используя жадный алгоритм.
3. Реализовать задачу о выборе заявок, используя жадный алгоритм.
4. Реализовать задачу о вычислении чисел Фибоначчи, используя
динамическое программирование.
======================================================
5. Реализовать алгоритм поиска в графе, используя обход в глубину
(матрица смежности).
6. Реализовать алгоритм поиска в графе, используя обход в глубину
(списки смежности).
46
7. Реализовать алгоритм поиска в графе, используя обход в ширину
(матрица смежности).
8. Реализовать алгоритм поиска в графе, используя обход в ширину
(списки смежности).
======================================================
9. Реализовать задачу о наибольшей общей последовательности используя
динамическое программирование.
10. Реализовать задачу о наибольшей увеличивающейся
последовательности используя динамическое программирование.
11. Реализовать задачу о порядке перемножения матриц используя
динамическое программирование.
12. Реализовать задачу о редакционном расстоянии используя
динамическое программирование.
47
ПРАКТИЧЕСКАЯ РАБОТА № 03.
ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ
Цель
Закрепить навыки разработки ООП-приложений. Концепция ООП очень быстро завоевала популярность при разработке программных решений за счет применения различных механик. Инкапсуляция позволила улучшить безопасность при работе с данными, полиморфизм и наследование позволили уменьшить объемы кода и увеличить его повторное использование.
Теория
Инкапсуляция – в информатике размещение в одном компоненте данных и методов, которые с ними работают. Для реализации этого механизма потребуется две вещи: компонент, позволяющий хранить в себе как данные, так и функции для их обработки, а также механизм сокрытия, который бы ограничивал доступ к данным внутри таких компонент.
В качестве компонента было введено понятие класса. Класс – это элемент, описывающий абстрактный тип данных и его частичную или полную реализацию. Класс может включать в себя множество элементов (некоторые будут специфичны только для определенных языков программирования), но, как минимум, они имеют поля для хранения данных и методы (функции) для обработки данных.
Механизм сокрытия данных реализован через модификаторы доступа. Модификаторы доступа применяются к любым элементам класса. Они позволяют как полностью закрывать доступ к элементам класса (модификатор private) другим классам, так и полностью или частично открывать доступ (модификаторы public или protected) для других классов.
Класс задается с помощью ключевого слова «class» далее указывается имя класса, открывающая фигурная скобка «{», элементы класса и закрывающая фигурная скобка «}» (листинг 3.1).
48
class Class1
{ // элементы класса
}
Листинг 3.1 – Пример создания класса Поля в классе задаются следующим образом (листинг 3.2): <модификаторы> <тип данных> <имя поля>;
class Class1
{ private int field1;
protected double field2;
public string Name;
}
Листинг 3.2 – Класс с 3 полями Методы класса задаются по следующему шаблону: <модификаторы> <тип возвращаемого значения / void> <имя метода>
(передаваемые параметры) { <тело метода> }
Если метод должен возвращать что-то, то после модификаторов
указывается тип возвращаемого значения. Если же метод не должен ничего возвращать, то указывается ключевое слово void. Также, если указано, что метод возвращает значение, то в теле метода обязателен вызов оператора
return.
В качестве передаваемых параметров указываются переменные (<тип
данных> <имя переменной>). Если в метод передается более одного параметра, то они указываются через запятую (листинг 3.3).
class Class1
{ private int field1;
protected double field2;
public string Name;
public Class1() { InitValues(); }
private void InitValues() { var random = new Random(); field1 = random.Next(10, 100); field2 = random.NextDouble();
49
}
protected void ChangeName(string newName) { Name = newName; }
public int GetValue() { return field1; }
public double GetData(string stringParam, int coef) { if (stringParam == Name) { return field2; } field2 = field1 * coef; return field2; }
}
Листинг 3.3 – Класс с полями и методами
Для того, чтобы обращаться к полям класса или вызывать методы класса
необходимо создать экземпляр класса или объект класса. Каждый объект класса несет в себе свой собственный уникальный набор значений. При этом все объекты, созданные от одного класса, имеют одинаковый набор полей и методов. Но значения в полях у каждого объекты будут свои, отличные от значений полей у других объектов от этого же класса (листинг 3.4).
Class1 cl1 = new Class1(); Class1 cl2 = new Class1();
Console.WriteLine("Values cl1: {0} cl2: {1}", cl1.GetValue(), cl2.GetValue());
Листинг 3.4 – Создание объектов класса и вызов методов
Результат будет следующим (рисунок 3.1).
Рисунок 3.1 – Результат работы
Наследование – это процесс, посредством которого один объект может
приобретать свойства другого. Точнее, объект может наследовать основные свойства другого объекта и добавлять к ним черты, характерные только для него. Класс, от которого произошло наследование, называется базовым или
50
родительским. Классы, которые произошли от базового, называются потомками, наследниками или производными классами.
Механизмы наследования позволяют создавать производные классы,
взяв за основу все не закрытые методы и элементы базового класса. Объекты производного класса свободно могут использовать все, что создано и отлажено в базовом классе. При этом, основная идея в том, что в производном классе, добавляется новый код для усовершенствования программы: добавление новых элементов, методов и т.д. При всем этом, базовый класс останется нетронутым.
Выделяют два вида наследования: расширение, когда имеется класс с
полной (базовый класс) или частичной (абстрактный класс) логикой и он расширяется новым классом, и реализация, когда имеется описание возможных действий и создается класс, который реализует описанные действия.
При расширении базового класса может возникнуть потребность
изменить логику некоторых методов базового класса. Есть два способа, первый, если к базовому классу по каким-то причинам нет доступа, то метод переопределяется с помощью модификатора new. Второй способ реализуется в 2 шага: в базовом классе у метода прописывается модификатор virtual, а в дочернем классе метод переопределяется через модификатор override. Важное негласное правило переопределения метода, что в дочернем методе в переопределенном методе вызывать переопределяемый метод базового класса.
Есть еще одна особенность при наследовании от базового класса, если у
него есть несколько конструкторов, либо один, но с передаваемыми параметрами. Так как, при создании экземпляра дочернего класса, по сути, создается экземпляр и базового класса, то возникает вопрос, а какой конструктор базового класса вызывать и как в него передавать параметры, если требуется. В таком случае, в дочернем классе потребуется прописать
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]