Загрузка данных
Содержание
Введение.......................................................................................................1
Понятие алгоритма и его свойства............................................................2
Классификация простейших алгоритмов в C++....................................3.1
Линейные алгоритмы...............................................................................3.2
Разветвляющиеся алгоритмы..................................................................3.3
Циклические алгоритмы..........................................................................3.4
Работа с массивами и базовые алгоритмы сортировки...........................4
Примеры реализованных программ..........................................................5
Заключение..................................................................................................6
Список использованных источников информации.................................7
Приложение 1. Листинги программ.........................................................8
Введение
В начале работы предполагалось что придется работать с большим объемом кода сразу но как оказалось любая большая программа состоит из маленьких частей кода - простейших алгоритмов. Без них невозможно двигаться дальше. Именно поэтому я выбрал тему «Простейшие алгоритмы на языке программирования C++». C++ я считаю одним из самых мощных и востребованных языков, и начать разбираться в нём лучше всего именно с алгоритмической базы.
Цель работы -изучить и самостоятельно реализовать базовые алгоритмы на C++. Чтобы достичь этой цели, я поставил перед собой несколько задач. Во-первых, разобраться, что вообще такое алгоритм и какими свойствами он обладает. Во-вторых, изучить три основные разновидности алгоритмов: линейные, разветвляющиеся и циклические. В-третьих, написать работающие программы на C++, которые наглядно демонстрируют каждый из этих типов. И наконец, проанализировать полученные результаты и понять, как эти знания пригодятся мне в будущем.
Объектом моего исследования стали алгоритмические конструкции языка C++. Предметом -сами простейшие алгоритмы и их программная реализация. При написании работы я использовал компилятор g++, среду разработки Code::Blocks, а также несколько хороших книг по основам программирования, которые перечислены в списке литературы. Всё, что здесь описано, я реально делал сам, все программы запускал и проверял. Общий объём работы составил 32 страницы.
Понятие алгоритма и его свойства
Прежде чем писать код, мне пришлось разобраться в теории. Алгоритм - это, по сути, точная инструкция, которая приводит от того, что у нас есть на входе, к тому, что мы хотим получить в итоге. В жизни мы постоянно выполняем алгоритмы, даже не задумываясь об этом. Например, утром я встаю, иду на кухню, наливаю чай - это простой алгоритм. В программировании алгоритмы записываются на языке, понятном компьютеру, в моём случае - на C++.
У любого алгоритма есть несколько обязательных свойств. Первое — дискретность, то есть разбиение на отдельные шаги, которые выполняются строго друг за другом. Компьютер не понимает расплывчатых указаний вроде «сделай как-нибудь». Второе свойство -детерминированность, или однозначность. На каждом шаге должно быть абсолютно понятно, что делать, без вариантов. Третье — результативность. Алгоритм обязан завершиться и дать какой-то результат, даже если это сообщение об ошибке. И четвёртое — массовость. Алгоритм должен работать не для одного набора данных, а для целого класса похожих задач.
В C++ любой алгоритм выражается через операторы, функции, циклы и условия. Например, самый простой алгоритм сложения двух чисел включает в себя ввод данных, операцию сложения и вывод результата. Я проверил это на практике и убедился, что даже в такой элементарной программе все перечисленные свойства соблюдаются. Без понимания этой базы невозможно было бы двигаться дальше.
Классификация простейших алгоритмов в C++
Изучая теорию, мы перешли к классификации. Оказалось, что по своей структуре все алгоритмы можно разделить на три основных типа, и каждый из них по-своему реализуется в C++.
Первый тип - линейные алгоритмы. Здесь всё идёт по цепочке: одно действие за другим, никаких ответвлений и возвратов. Компьютер просто читает команды сверху вниз и выполняет их. Это самый простой и понятный вид, с которого я и начал.
Второй тип - разветвляющиеся алгоритмы. Они позволяют программе выбирать, какой путь выполнения продолжить, в зависимости от каких-то условий. В C++ для этого используются операторы if, else и switch. Благодаря разветвлениям программа становится гибкой и может реагировать на разные ситуации.
Третий тип - циклические алгоритмы. Они нужны, когда одно и то же действие требуется повторить много раз. Вместо того чтобы писать один и тот же код сотню раз, я использую циклы for, while или do-while. Это экономит время и делает программу короче.
Отдельно от этих трёх типов мы рассмотрим алгоритмы обработки массивов, например поиск и сортировку. Такие алгоритмы обычно являются комбинацией циклов и условий. В этой рабрте мы последовательно разобререм каждый вид и реализовал его в виде работающих программ. Ниже подробно рассмотрим о каждом из них.
…………….
Линейные алгоритмы
Линейные алгоритмы - это самое начало. Я написал несколько таких программ, но лучше всего суть линейных алгоритмов показывает вычисление значения функции. Я выбрал квадратичную функцию y = ax² + bx + c.
Программа запрашивает у пользователя коэффициенты a, b, c и значение x, а затем выводит результат. В этом коде нет ни одного if, ни одного цикла - просто последовательные строки. Сначала программа выводит приглашение, потом считывает числа, потом производит вычисление и наконец выводит ответ.
Я тестировал эту программу с разными числами. Например, при a=1, b=0, c=0 и x=5 получается 25. Всё сходится. Конечно, возможности линейных алгоритмов сильно ограничены - они не умеют адаптироваться к данным. Но для понимания того, как работает поток выполнения, они идеально подходят. Именно на таких примерах я научился чувствовать порядок действий в программе.
………….
Разветвляющиеся алгоритмы
Как только я освоил линейные программы, мне захотелось сделать что-то более умное - то, что само принимает решения. И тут на помощь пришли разветвления. В C++ главный инструмент для этого - оператор if, а в некоторых случаях switch.
Для примера я написал программу, которая определяет, является ли год високосным. На первый взгляд задача простая, но в ней есть несколько условий, которые нужно проверить в правильном порядке. Год считается високосным, если он делится на четыре. Однако из этого правила есть исключения: если год делится на сто, то он не високосный. И ещё одно исключение: если год делится на четыреста, то он всё-таки високосный. Без разветвлений такую логику не реализовать.
В моей программе сначала проверяется сложное условие: год делится на четыре и при этом не делится на сто, либо год делится на четыреста. Если условие выполняется, программа выводит «Високосный», в противном случае - «Не високосный». Я протестировал программу на нескольких годах. Для 2020 года ответ правильный - високосный. Для 2021- не високосный. 1900 год, вопреки распространённому мнению, не високосный, и программа это тоже верно определяет. А вот 2000 год - високосный, потому что делится на четыреста.
Этот пример наглядно показывает, как разветвления делают программу умнее. Без них программа была бы просто линейным вычислителем, а с ними она уже может анализировать данные и давать разные ответы.
……….
Циклические алгоритмы
Следующий важный тип - циклические алгоритмы. Мне часто приходилось сталкиваться с задачами, где одно и то же действие нужно повторить много раз. Писать один и тот же код десятки раз бессмысленно, поэтому в C++ есть циклы. Я изучил три вида циклов: for, while и do-while. For удобен, когда заранее известно, сколько раз нужно повторить действие. While и do-while используются, когда количество повторений зависит от каких-то условий, которые могут измениться во время работы программы.
Для демонстрации я выбрал задачу вычисления факториала числа n. Факториал - это произведение всех целых чисел от единицы до n включительно. Например, факториал пяти равен сто двадцать. В этой задаче количество повторений строго равно n, поэтому логичнее всего использовать цикл for.
Моя программа запрашивает число n, затем в цикле перемножает все числа от единицы до n, сохраняя результат в переменной fact. Я протестировал её для нескольких значений. Для пяти получилось сто двадцать, для десяти -три миллиона шестьсот двадцать восемь тысяч восемьсот, что полностью соответствует правильному результату. После этого я переписал ту же программу с использованием цикла while, просто чтобы закрепить материал. Результат получился точно таким же.
Циклы оказались невероятно полезными. Без них невозможно представить себе серьёзную обработку данных - например, поиск в массиве или суммирование большого количества чисел. Циклы стали для меня настоящим открытием, потому что они превращают несколько строк кода в тысячи и даже миллионы операций.
---
Работа с массивами и базовые алгоритмы сортировки
Когда я разобрался с циклами и условиями, я перешёл к массивам. Массив - это просто набор ячеек одного типа, расположенных в памяти подряд. Но работать с массивами вручную, обращаясь к каждому элементу по отдельности, очень утомительно. Например, если в массиве сто элементов, писать сто строк кода - не вариант. Тут-то и пригождаются циклы.
Сначала я реализовал алгоритм линейного поиска. Идея очень простая: я загадываю некоторое число, которое нужно найти в массиве. Программа запускает цикл, который перебирает элементы один за другим и сравнивает каждый с искомым значением. Как только находится совпадение, программа запоминает индекс этого элемента и выходит из цикла с помощью break. Если поиск дошёл до конца массива, а элемент не нашёлся, значит, его нет в массиве. Линейный поиск работает медленно на больших массивах, но для учебных целей он идеален, потому что очень нагляден.
Потом я взялся за сортировку. Я выбрал самый простой алгоритм - сортировку пузырьком. Его суть в том, что я несколько раз прохожу по массиву и сравниваю соседние элементы. Если левый элемент больше правого, они меняются местами. Самые большие элементы постепенно «всплывают» в конец массива, как пузырьки в воде. Для этого нужны два вложенных цикла: внешний отвечает за количество проходов, внутренний - за сравнение соседних элементов.
Сортировка пузырьком - не самая быстрая, но она очень простая для понимания. Я запустил её на массиве из десяти чисел, и после завершения работы цикла массив оказался полностью отсортирован по возрастанию. Это был очень приятный момент, когда я увидел, как работают вложенные циклы.
---
Примеры реализованных программ
В ходе работы я создал несколько полноценных программ, в которых объединил всё изученное. Расскажу о каждой подробнее.
Первая программа - простой калькулятор. Пользователь вводит два числа, а затем выбирает операцию из предложенных: сложение, вычитание, умножение или деление. Для выбора действия я использовал оператор switch. Программа проверяет, какую операцию выбрал пользователь, и выполняет соответствующие вычисления. Если пользователь пытается разделить на ноль, программа выводит предупреждение об ошибке. Это пример разветвляющегося алгоритма, который к тому же обрабатывает исключительную ситуацию.
Вторая программа - таблица умножения. Она выводит на экран таблицу Пифагора размером десять на десять. Для этого я использовал вложенные циклы. Внешний цикл идёт по строкам, внутренний - по столбцам. На каждом шаге программа вычисляет произведение номера строки на номер столбца и выводит результат. Получается аккуратная квадратная таблица. Это отличный пример того, как циклы могут автоматизировать рутинную работу.
Третья программа - поиск максимального значения в массиве. Программа сначала заполняет массив случайными числами, а затем запускает цикл, который сравнивает каждый элемент с текущим найденным максимумом. В начале цикла максимумом считается первый элемент. Если очередной элемент оказывается больше, он становится новым максимумом. После завершения цикла программа выводит наибольшее число. Здесь снова используется цикл, но уже с условием внутри.
Все эти программы я полностью отладил, протестировал на разных входных данных и убедился, что они работают корректно. Полные листинги кода можно найти в приложении в конце работы.
---
Заключение
В начале работы казалось что простейшие алгоритмы это легко и неинтересно. Но при более глубоком изучении в тему, стало понятно что именно на этой базе строится всё остальное. Без линейных алгоритмов нельзя написать ни одной программы вообще. Без разветвлений программа всегда будет делать одно и то же, независимо от ситуации. Без циклов невозможно обрабатывать большие объёмы данных.
За время работы над проектом я не просто прочитал теорию. Я написал и отладил множество программ, начиная от простейшего калькулятора и заканчивая сортировкой массива. Я научился чувствовать поток выполнения программы, понимать, где нужно поставить условие, а где - цикл. Я убедился, что C++ даёт программисту полный контроль над алгоритмами, но требует внимательности и аккуратности.
Все задачи, которые я поставил перед собой во введении, выполнены. Я изучил понятие алгоритма и его свойства, разобрал три основных типа алгоритмов, реализовал их на C++, а также рассмотрел примеры работы с массивами. Этот проект пригодится мне в дальнейшем при изучении более сложных тем, таких как сортировка быстрым методом, рекурсия или структуры данных. Я доволен результатом и считаю, что работа удалась.