Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Отладка программных решений. Учебно-методическое пособие для студентов направлений подготовки бакалавриата 09.03.03 «Прикладная информатика», 09.03.04
.pdf
31
Пример
1 3 6
4 9 7
0 5 3
после сортировки:
0 1 3
3 4 5
6 7 9
8. Дан целочисленный двумерный массив размера N*N. Упорядочить
элементы в матрице по возрастанию (справа налево, снизу-вверх)
Пример
1 3 6
4 9 7
0 5 3
после сортировки:
9 7 6
5 4 3
3 1 0
========================================================
9. Дан целочисленный двумерный массив размера N*N. Отсортировать
элементы по периметру матрицы по возрастанию. Направление: слева
направо, сверху вниз.
Пример
1 6 3
4 7 9
0 3 6
после сортировки:
0 1 3
9 7 3
6 6 4
10. Дан целочисленный двумерный массив размера N*N. Отсортировать
элементы по периметру матрицы по убыванию. Направление: слева
направо, сверху вниз.
Пример
1 6 3
4 7 9
0 3 6
после сортировки:
9 6 6
0 7 4
1 3 3
11. Дан целочисленный двумерный массив размера N*N. Отсортировать
матрицу по возрастанию ниже побочной диагонали. Направление: слева
направо, сверху вниз.
Пример:
после сортировки:

32
1 6 3
4 7 9
0 3 6
1 6 3
4 7 3
0 6 9
12. Дан целочисленный двумерный массив размера N*N. Отсортировать
матрицу по убыванию выше главной диагонали. Направление: слева
направо, сверху вниз.
Пример:
1 6 3
4 7 9
0 3 6
после сортировки:
6 4 3
1 7 9
0 3 6

33
ПРАКТИЧЕСКАЯ РАБОТА № 02.
АЛГОРИТМЫ И СТРУКТУРЫ ДАННЫХ
Цель
Закрепить навыки применения различных алгоритмов и использования
различных структур данных. Любая программа состоит из двух блоков:
данных (информации), которые следует обработать и алгоритмы, с помощью
который выполняется обработка этих данных. И для эффективной работы
программы важно выбирать нужные структуры данных для хранения
информации, которые позволяют за минимальный объем ресурсов и времени
извлечь или поместить информацию в структуру данных и важно выбирать
оптимальные алгоритмы обработки этих структур данных, для более быстрого
выполнения задач.
Теория
Структуры данных, применяемые в программировании можно
рассматривать двояко. Во-первых, под структурой можно понимать
совокупность информации по некому объекту реального мира, которые
следует преобразовать в программный код. В таком случае, структура – это
набор полей, описывающий определенные характеристики объекта реального
мира. Даже элемент программирования, через которые описывались такие
объекты изначально, назывался struct (это затем ему на смену пришел уже
class). Во-вторых, под структурой понимается способ хранения набора данных
(скорее всего, однотипных) и доступа к элементам набора данных. В таком
случае, структура – это инструмент программиста для оптимальной работы с
данными. Тут становится важным как элементы (записи) хранятся в структуре,
как помещаются в структуру (как много времени занимает операция вставки),
как выполняется поиск элемента в структуре (опять же, за какое время
выполняется поиск). И выбор структуры данных зависит от целей, под
которые он должен применятся. Если, например, имеется много вставок в

34
структуру, а выборок минимальное количество (или выполняются проходы по
всем элементам структуры всегда), то логичнее использовать структуру с
минимальными затратами на вставку. Если же критичным будет поиск
элементов, то следует отдавать предпочтение структурам, у которых вставка
может занимать больше время и ресурсы, но, при этом, затраты на поиск будут
минимальны. Так же, может быть важен порядок расположения элементов,
либо порядок их добавления в набор и под эти задачи выбирается
соответствующая структура, позволяющая решать эти задачи.
Выделяют следующие структуры данных:
Массив. Как говорилось ранее, массив – это упорядоченная
коллекция однотипных элементов, расположенная в памяти
непрерывно. Из плюсов массива можно выделить быстрый доступ
к элементам (доступ, не поиск), быстрая вставка (при условии, что
не требуется изменять размер массива). Из минусов – долгий
поиск (порой, необходимо выполнять проход по всем элементам
массива для получения результата), фиксированный размер (и
трудоемкая операция изменения размера массива)
Список. Список – это коллекция элементов, каждый из которых
имеет ссылку на следующий элемент (как минимум). Выделяют
односвязные списки (когда у элемента есть ссылка только на
следующий элемент в списке) и двусвязные списки (у элемента
есть ссылка на следующий элемент в списке и на предыдущий). Из
плюсов – быстрая вставка и быстрое удаление. Из минусов –
долгий поиск и долгая операция обращения к элементу по индексу
(по сути, нужно идти с первого элемента списка, через каждый
элемент до нужного и никакая арифметическая операция, как в
массиве, не сможет сократить это время). Важно отличать тип
данных List, который встречается во многих языках
программирования. Данный тип строится на динамически

35
расширяемом массиве и не является реализацией структуры
данных «Список».
Стек/Очередь. Данные структуры имеют общий принцип работы с
данными, так что их стоит рассматривать вместе. И в стеке, и в
очереди фиксируется порядок добавления элементов в структуру.
В очереди порядок прямой – элемент, который пришел раньше
будет располагаться ближе к началу структуры (FIFO – first in, first
out, первый пришел, первый ушел). У очереди есть ограничение,
что доступ имеется только к первому элементу структуры. Для
получения доступа к следующему элементу, необходимо извлечь
из структуры первый элемент и т.д. В стеке порядок расположения
обратный, элемент, который был добавлен в стек последним будет
первым элементом структуры (LIFO – last in, first out, последним
пришел, первым вышел). В остальном ограничения аналогичны
очереди. Такие структуры применяются только в случае, когда
важен порядок хранения элементов. Например, если имеется
очередь задач на выполнение в операционной системе, новые
задачи встают в конец очереди и ожидают, пока все задачи,
которые уже были в очереди до них не выполнятся.
Дерево. Дерево – это структура данных, похожая на древовидную
структуру, когда от общего «ствола» отделяются «ветки», от
которых также могут отделяться «ветки» и так далее до «листков».
У дерева выделяют следующее элементы: корневой узел – самый
верхний узел дерева (первый элемент структуры), корень – одна из
вершин, по желанию наблюдателя (условно говоря, элемент
дерева над которым в данный момент выполняется обработка),
лист, листовой или терминальный узел – узел, не имеющий
дочерних элементов, внутренний узел – любой узел дерева,
имеющий потомков, и таким образом, не являющийся листовым

36
узлом. Деревья бывают разные, бинарные (двоичные),
префиксные, экспоненциальные, красно-черные, дерево 2-3-4 и
т.п. Ключевым преимуществом деревьев является быстры поиск,
который, зачастую, не требует обхода по всем элементам
структуры для достижения результата. Но, вставка в такое дерево
может занимать больше ресурсов, нежели вставка, например, в
список или массив.
Хеш-таблица. Это структура, где для каждого значения имеется
ключ, по которому к нему можно обратиться. При этом такой ключ
будет уникальным и в структуре не будет другого значения с
таким же ключом. Данная структура отличается от иных тем, что
доступ к элементу осуществляется по ключу, а не по порядковому
номеру (индексу). Для проверки уникальности ключа
добавляемой записи (что нет в структуре записи с таким же
ключом) используется операция расчета хеша. Эта же операция
используется, когда необходимо получить доступ к элементу по
ключу. По сути, в структуре хранятся пары: хеш ключа и значение,
доступное по этому ключу. Вставка в такую струкутру может
занимать больше времени, по сравнению со вставкой, например, в
массив (так как требуется рассчитать хеш). Как и стек/очередь
используется для хранения данных в специфической форме.
Практически все структуры, рассмотренные здесь относятся к
абстрактным типам данных (за исключением массива и списка). Для
абстрактных типов характерен акцент на взаимодействие между элементами
или доступ к элементам, нежели на способе хранения элементов. Поэтому, при
их реализации для хранения элементов используют либо массивы (чаще
всего), либо списки.
Под алгоритмом понимают набор действий, направленных для
достижения цели/задачи. Алгоритм – это любая конечная последовательность
основных математических и логических действий, однозначно определяющих

37
процесс преобразования исходных данных в искомые результаты решения
задачи. Любой алгоритм представляет собой описание некоторой
упорядоченной совокупности действий над определенными объектами. Для
вычислительных алгоритмов объекты действий – это данные Исходя из этого
определения можно выделить следующие особенности алгоритмов:
Определенность, т.е. общепонятность и точность. Все
предписания алгоритма должны допускать однозначную
трактовку и быть понятны исполнителю алгоритма.
Массовость, т.е. возможность использования различных данных
при решении однотипных задач. Алгоритм должен давать решение
целой группы задач, отличающихся исходными данными, а не
одной задачи с единственным набором данных.
Результативность, т.е. направленность на получение искомого
результата.
Дискретность, при выполнении разбивается на конечную
последовательность действий или шагов. Работа алгоритма
должна заканчиваться за определенное количество шагов.
Конечность, т.е. должен выполняться за конечное время. Общее
время работы алгоритма должно находиться в разумных пределах.
Тогда можно говорить об эффективности алгоритма.
Важным является эффективность алгоритма. Чем эффективнее
алгоритм, тем меньше ему требуется ресурсов для достижения цели.
Фактически, решить можно практически любую задачу, вопрос будет в
затрачиваемых для этого ресурсов, как физических (память, процессоры и
т.п.), так и временных.
Поэтому для решения многих типовых задач были разработаны
алгоритмы для их наиболее эффективного решения. Какие-то из них
позволяют экономить вычислительные мощности, какие-то из них позволяют
выполнять задачу с меньшими временными затратами.

38
В процессе реализации алгоритмов решения многих задач возникает
подзадача упорядочивания (сортировки) данных, как исходных, так и
итоговых. Так как задача встречается довольно часто, было разработано
больше количество алгоритмов сортировки, нацеленных на сокращение
вычислительных и временных затрат. Некоторые из этих алгоритмов
позволяют за короткий промежуток времени отсортировать большие наборы
данных, но при этом могут требовать большие вычислительные мощности под
это. Другим алгоритмам не требуется больше количество вычислительных
мощностей, но они проигрывают по времени работы. Некоторые алгоритмы к
своим преимуществам могут отнести простоту реализации (как правило, в
ущерб времени выполнения).
Вот некоторые из алгоритмов сортировки:
пузырьковая сортировка;
сортировка вставками;
сортировка слиянием;
сортировка перемешиванием;
сортировка выбором;
быстрая сортировка;
гномья сортировка.
Как и было сказано выше, они отличаются сложностью реализации,
скоростью работы и затрачиваемыми вычислительными ресурсами. Для
определения, какой алгоритм выбирать для решения задачи сортировки
данных, можно использовать оценку алгоритма по времени эффектности
использования памяти:
При оценки временных затрат выделяют худшее, среднее и
лучшее время работы алгоритма, исходя из размеров сортируемой
коллекции. Для алгоритма считается хорошее время работы, если
оно укладывается в O( ) и плохое время, если это O(n2).
Идеальное временем считается O(n);

39
В процессе работы некоторые алгоритмы запрашивают
дополнительные объемы памяти для хранения промежуточных
результатов. Как правило, эти алгоритмы требуют O( )
дополнительной памяти. Если алгоритму для работы не требуется
дополнительная память, то его относят к алгоритмам сортировки
на месте.
Таким образом, идеальным будет алгоритм сортировки, работающий за
время O(n) и не потребляющий дополнительную память. На деле, таких
алгоритмов нет и всегда требуется выбор, либо использовать дополнительную
память, либо проигрывать во времени работы.
Помимо задач упорядочивания элементов коллекций алгоритмы
используются много где еще. Например, для поиска оптимального решения
задачи. Среди таких алгоритмов выделяют жадные алгоритмы. Подобные
алгоритмы в процессе работы выбирают наилучший исход на каждой
итерации в расчете, что это даст итоговый наилучший по оптимальности
результат. Однако, на деле, это далеко не всегда так. Из-за такого подхода к
решению задачи не существует какого-либо общего критерия оценки
применимости жадного алгоритма.
И главное, к следующему классу задач жадные алгоритмы не дают
оптимального решения:
задача коммивояжера;
задача минимальной раскраски графа;
задача разбиения графа на подграфы;
задача выделения максимальной клики;
задачи, связанные с составлением расписаний.
Другой подход к решению задач – это применение подхода
динамического программирования. Этот подход подразумевает разбиение
сложной задачи на более простые подзадачи. Динамическое
программирование применяется к задачам, которые можно представить, как

40
набор перекрывающихся подзадач. При этом, у таких подзадач сложность
будет меньше, чем у исходной задачи. В этом случае можно получить
значительный выигрыш по времени выполнения алгоритма, по сравнению с
«наивными» методами.
В отличии от обычного подхода в решении сложной задачи (когда
решение задачи – это сумма решений всех ее подзадач), динамическое
программирование стремится решить каждую подзадачу только один раз, за
счет чего сократить количество вычислений. Наибольший выигрыш такой
подход дает в случае, когда количество повторяющихся подзадач велико.
Существует два способа решения задач в динамическом
программировании:
Нисходящий. Задача разбивается на подзадачи меньшего размера,
затем выполняется решение подзадач, и комбинирование
решенных подзадач для решения исходной задачи. В данном
способе запоминаются решения подзадач для их повторного
использования.
Восходящий. Заранее определяется спектр подзадач, которые
понадобятся для решения исходной задачи и выполняется расчет
этих подзадач. Затем подзадачи используются для построения
решения исходной задачи.
Динамическое программирование пользуется следующими свойствами
задачи:
перекрывающиеся подзадачи;
оптимальная подструктура;
возможность запоминания решения часто встречающихся
подзадач.
Классические задачи динамического программирования
Задача о наибольшей общей подпоследовательности.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
