
- •Оглавление
- •Введение
- •1. Рекомендации по изучению теоретического материала
- •1.1. Общие указания
- •1.2. Рекомендации по конкретным разделам курса
- •1.3. Методология обобщенного программирования
- •Почему не интерфейсы?
- •Вызов объекта
- •Реализация компараторов
- •Техника traits
- •2. Рекомендации по подготовке эссе, рефератов и докладов
- •2.1. Эссе: рекомендации по подготовке
- •2.2. Рефераты: рекомендации по подготовке
- •2.3. Доклады: рекомендации по подготовке
- •2.4. Моделирующие программы: рекомендации по разработке
- •3.2. Домашнее задание №2. Использование алгоритмов и контейнеров данных в прикладной задаче. Задачи домашнего задания
- •Задание
- •Требования к отчетности
- •Предлагаемые этапы выполнения задания
- •Теоретический материал, необходимый для выполнения домашнего задания
- •Функциональный и объектно-ориентированный подходы к программированию – краткое описание
- •Основы uml
- •Понятие агрегации в объектно-ориентированном программировании
- •Рекомендованные правила оформления исходных текстов
- •4.1. Правила выбора идентификаторов
- •4.2. Выравнивание исходных текстов Символ табуляции запрещён
- •Выравнивание блоков
- •Пробелы
- •Длинные операторы
- •4.3. Комментарии
- •Заключение
- •Литература
- •Кафедра компьютерной фотоники
2. Рекомендации по подготовке эссе, рефератов и докладов
Студентам рекомендуется подготовка эссе, рефератов и/или докладов по предлагаемым ниже или самостоятельно выбранным (и согласованным с преподавателем) темам. В рамках подготовки эссе, реферата или доклада рекомендуется выполнить три работы:
Подготовка эссе или реферата на предлагаемую тему.
Подготовка доклада на выбранную тему.
Разработка программы, иллюстрирующей рассматриваемые алгоритмы или контейнеры.
2.1. Эссе: рекомендации по подготовке
Эссе представляет собой краткий текст, описывающий основные аспекты темы. В эссе должны быть подчеркнуты:
Задача, решаемая алгоритмом или контейнером.
Ключевые аспекты алгоритма, отличия от альтернативных решений.
Преимущества и недостатки рассматриваемого метода решения задачи.
Рекомендуемый объем эссе – около 2-3 страниц. Отмечу, что подготовка эссе в сравнении с подготовкой реферата требует более высокого уровня знаний в рассматриваемой области, умения в рамках сравнительно небольшого объема текста подчеркнуть все ключевые аспекты рассматриваемой проблемы.
Обязательно предоставление электронной версии эссе.
2.2. Рефераты: рекомендации по подготовке
Реферат – это работа, подготовленная на основе одного или нескольких литературных источников. В рамках подготовки реферата необходимо выделить в литературных источниках относящуюся к данной теме информацию, обобщить ее, выделить наиболее существенные моменты.
Реферат должен состоять из следующих разделов:
Введение. Во введении кратко описывается поставленная проблема.
Основная часть. В основной части описываются со ссылками на соответствующую литературу:
Задача, решаемая алгоритмом или контейнером.
Основной принцип работы данного программного объекта. В чем основное техническое решение, отличающее этот объект от других?
Важные особенности работы алгоритма или контейнера.
Характеристики рассматриваемого решения в сравнении с альтернативами.
Область применения алгоритма или контейнера (по замыслу авторов и в настоящее время).
Заключение. В заключении кратко описываются принцип работы, достоинства и недостатки данной технологии.
Список литературы, оформленный в соответствии с ГОСТ.
Рекомендуемый объем реферата – 7-12 страниц. Обязательно предоставление электронной версии реферата.
2.3. Доклады: рекомендации по подготовке
Доклад представляет собой выступление в рамках одного из занятий, посвященное алгоритму или контейнеру. В докладе необходимо отразить ключевые аспекты рассматриваемого механизма (аналогично требованиям к реферату).
Рекомендованный объем доклада – около 15 минут.
Доклад должен сопровождаться электронной презентацией. Примерный объем презентации – 10-15 слайдов PowerPoint. Слайды должны содержать:
Вводный слайд – тему доклада, фамилию и имя автора.
Основные тезисы доклада.
Иллюстрирующие доклад рисунки, схемы и таблицы.
Информацию о наиболее важных характеристиках алгоритма или контейнера.
2.4. Моделирующие программы: рекомендации по разработке
Программы, реализующие тот или иной алгоритм или контейнер, должны решать ту задачу, для разработки которой этот алгоритм или контейнер был создан. Их исходные тексты должны быть качественно оформлены (см. гл. 4). Разработчик программы должен быть в состоянии демонстрировать решения, принятые при разработке алгоритма и контейнера, и их воплощение в исходном коде программы.
Программы, иллюстрирующие работу стандартных алгоритмов и контейнеров, должны решать реалистичную задачу разработки ПО (или несколько таких задач).
Для хорошо подготовленных студентов рекомендуется (и будет высоко оцениваться) разработка демонстрационных программ с графическим интерфейсом, иллюстрирующих работу того или иного алгоритма. Например, это может быть программа, предлагающая пользователю ввести массив и демонстрирующая, как будет производиться его сортировка тем или иным методом.
Для разработки демонстрационной программы могут выбираться не только перечисленные ниже алгоритмы и контейнеры, но и любые другие (по согласованию с преподавателем).
2.5 Рекомендуемые темы для эссе, рефератов и докладов
1. Методы сортировки с сохранением порядка равных элементов.
2. Методы сортировки за линейное время.
3. AVL-деревья.
4. Хэш-таблица с разрешением коллизий методом списков и универсальным хэшированием.
5. Хэш-таблица с использованием квадратичного исследования и метода умножения.
3. Домашние задания
Домашнее задание 1 относится к первому модулю. Стоимость в баллах в соответствии с программой курса - 8.
Домашнее задание 2 относится ко второму модулю. Стоимость – 30 баллов.
3.1. Домашнее задание №1.
Задачи домашнего задания
Закрепление знаний об алгоритмах сортировки, работающих за время O(NlogN).
Восстановление навыков программирования на C++, полученных в рамках предыдущих курсов.
Задание
Разработать программу на языке C++, выполняющую сортировку слиянием массива вещественных чисел.
Программа должна позволять ввести с экрана несколько чисел и сортировать их по возрастанию.
Достаточна разработка консольного приложения.
Разрешается ограничить количество элементов в массиве константой, фиксируемой в момент компиляции.
Требования к отчетности
В качестве отчета студент предоставляет в электронном виде программу на языке C++, выполняющую сортировку массива.
Предлагаемые этапы выполнения задания
Изучение теоретического материала.
Создание пустого консольного приложения в среде Visual Studio 2005 [7].
Разработка программы.
Отладка программы.
Теоретический материал, необходимый для выполнения домашнего задания
Сортировка слиянием (MergeSort)
Алгоритм сортировки слиянием [2] основан на следующих принципах:
Если массив состоит из двух отсортированных частей (например, равных, но это не обязательно), то мы можем выполнить сортировку массива за время O(N).
Действительно, если последовательности A[0]..A[K-1] и A[K]..A[N-1] отсортированы, то для получения минимального элемента достаточно сравнить A[ 0 ] и A[ K ]. Найденный элемент попадает в результирующий массив и исключается из рассмотрения. Чтобы найти минимальный из оставшихся элементов, снова достаточно сравнить минимальные элементы подпоследовательностей. Если одна из подпоследовательностей закончилась – оставшиеся элементы просто берем из другой.
Слияние отсортированных последовательностей иллюстрируется на рис. 1.
Рис. 1. Слияние подпоследовательностей
На каждом шаге сравниваются два минимальных элемента из двух подпоследовательностей и меньший из них переносится в результирующую последовательность. Когда одна подпоследовательность заканчивается – оставшиеся элементы второй переносятся в результирующую последовательность.
Массив из двух элементов всегда состоит из двух отсортированных частей.
Соответственно, мы можем сначала разбить наш массив на группы по 2 элемента и сортировать их указанным методом. Таких групп будет N/2. Если останется 1 лишний последний элемент – не страшно, он считается уже отсортированной группой.
Далее мы рассматриваем группы из 4 элементов (опять же, не страшно, если последняя группа будет меньше). Каждая группа состоит из двух только что отсортированных двухэлементных групп. Значит, мы можем применить алгоритм из 1-ого пункта.
Продолжая объединение групп, в итоге мы получим отсортированный массив.
На шаге K рассматриваются группы из 2K элементов. Время сортировки одной группы O(2K), число групп N/2K, общая длительность шага O(N).
Число таких шагов – log2N, т.к. размер группы увеличивается в два раза на каждом шаге и сортировка заканчивается, когда он станет равным N.
Таким образом, общая длительность сортировки – O(NlogN).
Сортировка слиянием иллюстрируется на рис. 2.
Рис. 2. Сортировка слиянием
Описание работы с массивами в языке программирования C++
Массивом [3] называется совокупность пронумерованных данных, размещаемых в памяти подряд, одно значение за другим. В массиве можно обеспечить быстрое обращение к элементу по номеру, т.к.
Ai=A+i*S, [3.1]
где Ai - адрес элемента i, A – адрес начала массива, S – размер элемента.
Массив иллюстрируется на рис. 3.
Рис. 3. Размещение массива в памяти.
В языке программирования C++ [3] массив – один из составных типов данных. Массив объявляется в виде
TYPE NAME[ SIZE ];
где TYPE – тип элемента массива (должен быть корректным типом данных), NAME – имя массива, SIZE – размер массива (должен быть константой). Например:
double Arr[ 10 ];
const int TextSize=4096;
char Text[ TextSize ];
Для того, чтобы обратиться к элементу массива, мы пишем NAME[ INDEX ], где NAME – имя массива, INDEX – номер элемента. Например: Arr[0]=Arr[1]+Arr[2];
Циклы в C++
В случае, если одна и та же операция (например, ввод данных пользователем, их обработка моделируемым устройством и вывод данных) должна быть выполнена в ходе программы многократно, используются циклы.
В C++ существуют три вида цикла:
1. Цикл while (с предусловием).
while ( <условие> )
<операция>
Пока выполнено условие – выполнять операцию.
Пример:
char a[200];
…. //заполнение строки чем-нибудь
int i = 0;
while ( i < 200 && a[i] !=’A’ )
i++;
Этот код бежит по строке либо до конца строки, либо пока не встретит букву ‘A’. Так мы можем узнать, где в строке первая буква ‘A’.
2. Цикл do-while (с постусловием).
do
<операция>
while ( <условие> );
Повторяет операцию, пока выполнено условие. Хотя бы один раз операция точно будет выполнена (условие проверяется после выполнения операции и определяет, идти ли на следующий шаг).
Пример:
char res=0;
do
{
printf( ”Если устали – введите Y\n” );
scanf( “%c” , &res );
}
while ( res != ‘Y’ );
Этот код спрашивает у пользователя, не устал ли он. Если пользователь ввел Y (Yes) – программа выходит из цикла и идет дальше, иначе спрашивает еще раз.
3. Цикл for.
for ( <инициализация> ; <условие> ; <переход> )
<операция>
Вначале выполняется операция инициализации. После этого, если выполнено условие – выполняется операция и переход.
Пример:
for ( i = 0; i < 200 ; i = i + 2 )
A[i] = 0;
Этот код заполняет нулями четные элементы массива A с номером меньше 200.
Описание ввода-вывода в языке программирования C++
Языки C и C++ не имеют команд ввода-вывода, поскольку эти операции не могут быть реализованы независимо от конкретного компьютера. Существуют функции и классы в составе стандартной библиотеки языка, решающие задачи ввода-вывода.
Основной абстракцией ввода-вывода, используемой в библиотеке STL, является поток [3]. Потоком называется объект, из которого могут быть прочитаны данные (поток ввода) или в который могут быть записаны данные (поток вывода). В роли потока может выступать экран консольного приложения, файл, какой-либо датчик и т.д. – главное, чтобы для него был реализован класс с соответствующим интерфейсом.
Основными механизмами работы с потоком являются операторы потокового ввода (>>) и потокового вывода (<<). Например, чтобы в консольном приложении считать с экрана целое число, мы напишем:
int a;
std::cin >> a;
std::cin – это стандартный объект – поток ввода с экрана консольного приложения.
Аналогично, чтобы вывести на экран вещественное число и затем перейти на следующую строку, можно написать:
double b = 4.3;
std::cout << b << std::endl;
std::cout – стандартный объект, поток вывода на экран консольного приложения. std::endl – символ конца строки
Мы можем в одной строке вывести две величины благодаря тому, что результатом работы оператора потокового вывода является тот же самый поток, в который выполнялся вывод. И в этот поток можно вывести следующий символ.
Именно поэтому оператор потокового вывода, как правило, имеет синтаксис (я рассматриваю вариант реализации оператора как функции, а не как метода потока):
std::ostream& operator<<( std::ostream& str , SomeType somevalue )
{
…//Вывод в str somevalue
return str;
}
Благодаря этому синтаксису результатом операции std::cout << b является сам поток cout. И когда мы применяем к этому результату операцию << std::endl – символ конца строки выводится на экран, как мы и хотели.
Основные виды потоков:
std::cin, std::cout, std::cerr – стандартные потоки консольного ввода-вывода.
std::ifstream, std::ofstream – потоки файлового ввода-вывода.
std::istrstream, std::ostrstream – потоки ввода-вывода в строку.