OAP/t1l1.md at master · kolei/OAP · GitHub

1. Что такое алгоритм?

Понятие алгоритма такое же основополагающее для информатики, как и понятие
информации. Именно поэтому важно в нем разобраться.

Название “алгоритм” произошло от латинской формы имени величайшего
среднеазиатского математика Мухаммеда ибн Муса ал-Хорезми (Alhorithmi),
жившего в 783—850 гг. В своей книге “Об индийском счете” он изложил
правила записи натуральных чисел с помощью арабских цифр и правила
действий над ними “столбиком”, знакомые теперь каждому школьнику.
В XII веке эта книга была переведена на латынь и получила широкое
распространение в Европе.

Человек ежедневно встречается с необходимостью следовать тем или иным правилам,
выполнять различные инструкции и указания. Например, переходя через дорогу на
перекрестке без светофора надо сначала посмотреть направо. Если машин нет, то
перейти полдороги, а если машины есть, ждать, пока они пройдут, затем
перейти полдороги.

В математике для решения типовых задач мы используем определенные правила,
описывающие последовательности действий. Например, правила сложения дробных
чисел, решения квадратных уравнений и т. д. Обычно любые инструкции и правила
представляют собой последовательность действий, которые необходимо выполнить
в определенном порядке.

Для решения задачи надо знать, что дано, что следует
получить и какие действия и в каком порядке следует для этого выполнить.
Предписание, определяющее порядок выполнения действий над данными с целью
получения искомых результатов, и есть алгоритм.

Алгоpитм — заранее заданное понятное и точное пpедписание
возможному исполнителю совеpшить определенную последовательность действий
для получения решения задачи за конечное число шагов.

Это — не определение в математическом смысле слова, а, скорее,
описание интуитивного понятия алгоритма, раскрывающее его сущность.

Понятие алгоритма является не только одним из главных понятий математики,
но одним из главных понятий современной науки. Более того, с наступлением
эры информатики алгоритмы становятся одним из важнейших факторов
цивилизации [56].

Гибкие материалы:  Знаменитости, которые уверенно делают шпагат (23 фото)

Основные служебные слова

алг (алгоритм)сим (символьный)данодляда
арг (аргумент)лит (литерный)надоотнет
рез (результат)лог (логический)еслидопри
нач (начало)таб(таблица)тозначвыбор
кон (конец)нц (начало цикла)иначеиввод
цел (целый)кц (конец цикла)всеиливывод
вещ (вещественный)длин (длина)поканеутв
Общий вид алгоритма:

 алг название алгоритма (аргументы и результаты)
   дано условия применимости алгоритма
   надо цель выполнения алгоритма
 нач описание промежуточных величин
 |   последовательность команд (тело алгоритма)
 кон

Часть алгоритма от слова алг до слова нач называется
заголовком, а часть, заключенная между словами
нач и кон — телом алгоритма.

В предложении алг после названия
алгоритма в круглых скобках указываются характеристики (арг,
рез) и тип значения (цел, вещ, сим, лит или лог) всех
входных (аргументы) и выходных (результаты)
переменных.

Примеры предложений алг:

  • алг Объем и площадь цилиндра (арг вещ R, H, рез
    вещ
    V, S)
  • алг Корни КвУр(арг вещ а, b, c, рез вещ
    x1, x2, рез лит t)
  • алг Исключить элемент(арг цел
    N, арг рез вещ таб А[1:N])
  • алг Диагональ(арг цел N,
    арг цел таб A[1:N,1:N], рез лит Otvet)

Предложения дано и надо не обязательны. В них
рекомендуется записывать утверждения, описывающие
состояние среды исполнителя алгоритма,
например:

  1. алг Замена (арг лит Str1, Str2, арг рез лит Text)
    дано | длины подстрок Str1 и Str2 совпадают
    надо | всюду в строке Text подстрока Str1 заменена на Str2
    
  2. алг Число максимумов (арг цел N, арг вещ таб A[1:N], рез цел K)
    дано | N>0
    надо | К - число максимальных элементов в таблице А
    
  3. алг Сопротивление (арг вещ R1, R2, арг цел N, рез вещ R)
    дано | N>5, R1>0, R2>0
    надо | R - сопротивление схемы
    

Алгоритм – что это такое: виды и типы алгоритмов, применение

Алгоритм — это четкая последовательность действий, выполнение которой дает какой-то заранее известный результат. Проще говоря, это набор инструкций для конкретной задачи. Известнее всего этот термин в информатике и компьютерных науках, где под ним понимают инструкции для решения задачи эффективным способом.

Несмотря на схожесть со словом «ритм», происхождение названия иное. По одной из версий, «алгоритм» — неверный перевод фамилии древнего ученого аль-Хорезми, который писал трактаты по математике. Так наименование и закрепилось.

Сейчас под этим словом понимают любые последовательности действий, которые можно четко описать и разделить на простые шаги и которые приводят к достижению какой-то цели. Например, пойти на кухню, налить воду и положить в нее пакетик чая — это алгоритм для выполнения задачи «Заварить чай».

Алгоритмы в информатике — инструкции для компьютеров, набор шагов, который описывается программным кодом. Существуют конкретные алгоритмы для тех или иных действий, причем некоторые из них довольно сложные. Одна из целей использования алгоритмов — делать код эффективнее и оптимизировать его.

В общем смысле — абсолютно все живые и некоторые неживые существа, потому что любую последовательность действий, ведущую к цели, можно считать алгоритмом. Поиск еды животным — алгоритм, движения робота тоже описываются алгоритмом.

В узком смысле, в котором понятие используется в компьютерных науках, алгоритмами пользуются разработчики, некоторые инженеры и аналитики, а также специалисты по машинному обучению, тестировщики и многие другие. Это одно из ключевых понятий в IT.

Алгоритмы в информатике нужны для эффективного решения различных задач, в том числе тех, выполнение которых «в лоб» имеет высокую сложность или вовсе невозможно. На практике существуют алгоритмы практически для чего угодно: сортировки, прохождения по структурам данных, поиска элементов, фильтрации информации, математических операций и так далее.

Например, отсортировать массив можно в ходе полного перебора — это самое очевидное решение. А можно воспользоваться алгоритмом быстрой сортировки: он сложнее и не так очевиден, зато намного быстрее работает и не так сильно нагружает мощности компьютера. Строго говоря, полный перебор — это тоже алгоритм, но очень простой.

Существуют алгоритмически неразрешимые задачи, для решения которых нет и не может существовать алгоритма. Но большинство задач в IT разрешимы алгоритмически, и алгоритмы активно используются в работе с ними.

Алгоритмы применяются во всех направлениях IT и во многих других отраслях. Инструкции для автоматизированного станка или линии производства — алгоритмы, рецепт блюда — тоже. Поэтому в общем смысле алгоритмы нужны для чего угодно.

Дискретность. Алгоритм — не единая неделимая структура, он состоит из отдельных маленьких шагов, или действий. Эти действия идут в определенном порядке, одно начинается после завершения другого.

Результативность. Выполнение алгоритма должно привести к какому-либо результату и не оставлять неопределенности. Результат может в том числе оказаться неудачным — например, алгоритм может сообщить, что решения нет, — но он должен быть.

Детерминированность. На каждом шаге не должно возникать разночтений и разногласий, инструкции должны быть четко определены.

Массовость. Алгоритм обычно можно экстраполировать на похожие задачи с другими исходными данными — достаточно поменять изначальные условия. Например, стандартный алгоритм по решению квадратного уравнения останется неизменным вне зависимости от того, какие числа будут использоваться в этом уравнении.

Понятность. Алгоритм должен включать только действия, известные и понятные исполнителю.

Конечность. Алгоритмы конечны, они должны завершаться и выдавать результат, в некоторых определениях — за заранее известное число шагов.

Несмотря на слово «последовательность», алгоритм не всегда описывает действия в жестко заданном порядке. Особенно это актуально сейчас, с распространением асинхронности в программировании. В алгоритмах есть место для условий, циклов и других нелинейных конструкций.

Линейные. Это самый простой тип алгоритма: действия идут друг за другом, каждое начинается после того, как закончится предыдущее. Они не переставляются местами, не повторяются, выполняются при любых условиях.

Ветвящиеся. В этом типе алгоритма появляется ветвление: какие-то действия выполняются, только если верны некоторые условия. Например, если число меньше нуля, то его нужно удалить из структуры данных. Можно добавлять и вторую ветку: что делать, если условие неверно — например, число больше нуля или равно ему. Условий может быть несколько, они могут комбинироваться друг с другом.

Циклические. Такие алгоритмы выполняются в цикле. Когда какой-то блок действий заканчивается, эти действия начинаются снова и повторяются некоторое количество раз. Цикл может включать в себя одно действие или последовательность, а количество повторений может быть фиксированным или зависеть от условия: например, повторять этот блок кода, пока в структуре данных не останется пустых ячеек. В некоторых случаях цикл может быть бесконечным.

Рекурсивные. Рекурсия — это явление, когда какой-то алгоритм вызывает сам себя, но с другими входными данными. Это не цикл: данные другие, но «экземпляров» работающих программ несколько, а не одна. Известный пример рекурсивного алгоритма — расчет чисел Фибоначчи.

Рекурсия позволяет изящно решать некоторые задачи, но с ней надо быть осторожнее: такие алгоритмы могут сильно нагружать ресурсы системы и работать медленнее других.

Вероятностные. Такие алгоритмы упоминаются реже, но это довольно интересный тип: работа алгоритма зависит не только от входных данных, но и от случайных величин. К ним, например, относятся известные алгоритмы Лас-Вегас и Монте-Карло.

Основные и вспомогательные. Это еще один вид классификации. Основной алгоритм решает непосредственную задачу, вспомогательный решает подзадачу и может использоваться внутри основного — для этого там просто указываются его название и входные данные. Пример вспомогательного алгоритма — любая программная функция.

Алгоритмы могут записывать текстом, кодом, псевдокодом или графически — в виде блок-схем. Это специальные схемы, состоящие из геометрических фигур, которые описывают те или иные действия. Например, начальная и конечная точка на схеме — соответственно, начало и конец алгоритма, параллелограмм — ввод или вывод данных, ромб — условие. Простые действия обозначаются прямоугольниками, а соединяются фигуры с помощью стрелок — они показывают последовательности и циклы.

В схемах подписаны конкретные действия, условия, количество повторений циклов и другие детали. Это позволяет нагляднее воспринимать алгоритмы.

Понятие «сложность» — одно из ключевых в изучении алгоритмов. Оно означает не то, насколько трудно понять тот или иной метод, а ресурсы, затраченные на вычисление. Если сложность высокая, алгоритм будет выполняться медленнее и, возможно, тратить больше аппаратных ресурсов; такого желательно избегать.

Сложность обычно описывают большой буквой O. После нее в скобках указывается значение, от которого зависит время выполнения. Это обозначение из математики, которое описывает поведение разных функций.

Какой бывает сложность. Полностью разбирать математическую O-нотацию, как ее называют, мы не будем — просто перечислим основные обозначения сложности в теории алгоритмов.

  •  O(1) означает, что алгоритм выполняется за фиксированное константное время. Это самые эффективные алгоритмы.
  •  O(n) — это сложность линейных алгоритмов. n здесь и дальше обозначает размер входных данных: чем больше n, тем дольше выполняется алгоритм.
  •  O(n²) тоже означает, что чем больше n, тем выше сложность. Но зависимость тут не линейная, а квадратичная, то есть скорость возрастает намного быстрее. Это неэффективные алгоритмы, например с вложенными циклами.
  •  O(log n) — более эффективный алгоритм. Скорость его выполнения рассчитывается логарифмически, то есть зависит от логарифма n.
  •  O(√n) — алгоритм, скорость которого зависит от квадратного корня из n. Он менее эффективен, чем логарифмический, но эффективнее линейного.

Существуют также O(n³), O(nn) и другие малоэффективные алгоритмы с высокими степенями. Их сложность растет очень быстро, и их лучше не использовать.

Графическое описание сложности. Лучше разобраться в сложности в O-нотации поможет график. Он показывает, как изменяется время выполнения алгоритма в зависимости от размера входных данных. Чем более пологую линию дает график, тем эффективнее алгоритм.

O-нотацию используют, чтобы оценить, эффективно ли использовать ту или иную последовательность действий. Если данные большие или их много, стараются искать более эффективные алгоритмы, чтобы ускорить работу программы.

Мы приведем несколько примеров использования разных алгоритмов в отраслях программирования. На самом деле их намного больше — мы взяли только часть, чтобы помочь вам понять практическую значимость алгоритмов.

Разработка ПО и сайтов. Алгоритмы используются для парсинга, то есть «разбора» структур с данными, таких как JSON. Парсинг — одна из базовых задач, например в вебе. Также алгоритмы нужны при отрисовке динамических структур, выводе оповещений, настройке поведения приложения и многом другом.

Работа с данными. Очень активно алгоритмы применяются при работе с базами данных, файлами, где хранится информация, структурами вроде массивов или списков. Данных может быть очень много, и выбор правильного алгоритма позволяет ускорить работу с ними. Алгоритмы решают задачи сортировки, изменения и удаления нужных элементов, добавления новых данных. С их помощью наполняют и проходят по таким структурам, как деревья и графы. 

Отдельное значение алгоритмы имеют в Big Data и анализе данных: там они позволяют обработать огромное количество информации, в том числе сырой, и не потратить на это слишком много ресурсов.

Поисковые задачи. Алгоритмы поиска — отдельная сложная отрасль. Их выделяют в отдельную группу, в которой сейчас десятки разных алгоритмов. Поиск важен в науке о данных, в методах искусственного интеллекта, в аналитике и многом другом. Самый очевидный пример — поисковые системы вроде Google или Яндекса. Кстати, подробности об используемых алгоритмах поисковики обычно держат в секрете.

Машинное обучение. В машинном обучении и искусственном интеллекте подход к алгоритмам немного другой. Если обычная программа действует по заданному порядку действий, то «умная машина» — нейросеть или обученная модель — формирует алгоритм для себя сама в ходе обучения. Разработчик же описывает модель и обучает ее: задает ей начальные данные и показывает примеры того, как должен выглядеть конечный результат. В ходе обучения модель сама продумывает для себя алгоритм достижения этого результата.

Такие ИИ-алгоритмы могут быть еще мощнее обычных и используются для решения задач, которые разработчик не в силах разбить на простые действия сознательно. Например, для распознавания предметов нужно задействовать огромное количество процессов в нервной системе: человек просто физически не способен описать их все, чтобы повторить программно.

В ходе создания и обучения модели разработчик тоже может задействовать алгоритмы. Например, алгоритм распространения ошибки позволяет обучать нейросети. 

10. Какие циклы называют итерационными?

На каждом шаге вычислений происходит последовательное приближение к искомому результату и проверка условия достижения последнего.

Пример. Составить алгоритм вычисления бесконечной суммы

с заданной точностью  OAP/t1l1.md at master · kolei/OAP · GitHub  (для данной знакочередующейся бесконечной суммы требуемая
точность будет достигнута, когда очередное слагаемое станет по абсолютной
величине меньше OAP/t1l1.md at master · kolei/OAP · GitHub).

Вычисление сумм — типичная циклическая задача. Особенностью же нашей
конкретной задачи является то, что число слагаемых (а, следовательно, и число
повторений тела цикла) заранее неизвестно. Поэтому выполнение цикла должно
завершиться в момент достижения требуемой точности.

При составлении алгоритма нужно учесть, что знаки слагаемых
чередуются и степень числа  х  в числителях слагаемых возрастает.

Решая эту задачу “в лоб” путем вычисления на каждом  i-ом шаге частичной
суммы

S:=S ((-1)**(i-1)) * (x**i) / i ,
мы получим очень неэффективный алгоритм, требующий выполнения большого
числа операций. Гораздо лучше организовать вычисления следующим образом:
если обозначить числитель какого-либо слагаемого буквой  
р
 ,
то у следующего слагаемого числитель будет равен  
—р*х
 
(знак минус обеспечивает чередование знаков слагаемых), а само слагаемое  m  будет равно
 
p/i
 , где  
i
 — номер слагаемого.

Сравните эти два подхода по числу операций.

Алгоритм, в состав которого входит итерационный
цикл, называется итеpационным алгоpитмом. Итерационные алгоритмы
используются при реализации итерационных численных методов.

В итерационных алгоритмах необходимо обеспечить обязательное достижение
условия выхода из цикла (сходимость итерационного процесса).
В противном случае произойдет “зацикливание” алгоритма, т.е. не
будет выполняться основное свойство алгоритма —
результативность.

22. Упражнения

7.1. Запишите по правилам алгоритмического языка выражения:

[ Ответ ]

7.2. Запишите в обычной математической форме арифметические
выражения:

а)a / b ** 2;
б)a b/c 1;
в)1/a*b/c;
г)a**b**c/2;
д)(a**b)**c/2;
е)a/b/c/d*p*q;
ж)x**y**z/a/b;
з)4/3*3.14*r**3;
и)b/sqrt(a*a b);
к)d*c/2/R a**3;
л)5*arctg(x)-arctg(y)/4;
м)lg(u*(1/3) sqrt(v) z);
н)ln(y*(-sqrt(abs(x))));
о)abs(x**(y/x)-(y/x)**(1/3));
п)sqrt((x1-x2)**2 (y1-y2)**2);
р)exp(abs(x-y))*(tg(z)**2 1)**x;
c)lg(sqrt(exp(x-y)) x**abs(y) z);
т)sqrt(exp(a*x)*sin(x)**n)/cos(x)**2;
у)sqrt(sin(arctg(u))**2 abs(cos(v)));
ф)abs(cos(x) cos(y))**(1 sin(y)**2);

[ Ответ ]

7.3. Вычислите значения арифметических выражений при x=1:
а)abs(x-3)/ln(exp(3))*2/lg(10000);Решение:abs(1-3)=2; ln(exp(3))=3; lg(10000)=4; 2/3*2/4=0.33;б)sign(sqrt(sqrt(x 15)))*2**2**2;в)int(-2.1)*int(-2.9)/int(2.9) x;г)-sqrt(x 3)

**2**(sign(x 0.5)*3) tg(0);д)lg(x) cos(x**2-1)*sqrt(x 8)-div(2,5);е)sign(x-2)*sqrt(int(4.3))/abs(min(2,-1));ж)div(10,x 2)*mod(10,x 6)/max(10,x)*mod(2,5).[ Ответ ]

7.4. Запишите арифметические выражения, значениями которых являются:
а) площадь треугольника со сторонами a, b, c (a, b, c>0)
и полупериметром p; Ответ:sqrt(p*(p-a)*(p-b)*(p-c));

б) среднее арифметическое и среднее геометрическое чисел a, b, c,
d;в) расстояние от точки с координатами (x,y) до точки (0,0);
г) синус от x градусов; д) площадь поверхности куба (длина ребра равна а); е) радиус описанной сферы куба (длина ребра равна а); ж) координаты точки пересечения двух прямых, заданных уравнениями a1x b1y c1=0 и a2x b2y c2=0
(прямые не параллельны).
[ Ответ ]

7.5. Вычислите значения логических выражений: а)x*x y*y<=9 при x=1, y=-2Ответ: да;б)b*b-4*a*c<0 при a=2, b=1, c=-2;в)(a>=1) и (a<=2) при a=1.5;г)(a<1) или (a>1.2) при a=1.5;д)(mod(a,7)=1) и (div(a,7)=1) при a=8;е)не ((a>b) и (a<9) или (а*а=4)) при
a=5, b=4.[ Ответ ]

7.6. Запишите логические выражения, истинные только при выполнении указанных
условий: а)   x принадлежит отрезку [a, b] Ответ:(x>=a) и (x<=b); б)   x лежит вне отрезка [a, b]; в)   x принадлежит отрезку [a, b] или отрезку [c, d]; г)   x лежит вне отрезков [a, b] и [c, d]; д)   целое k является нечетным числом; е)   целое k является трехзначным числом, кратным пяти;ж)   элемент ai,j двумерного массива находится на пересечении
нечетной строки и четного столбца; з)   прямые a1x b1y c1=0 и a2x b2y c2=0
параллельны;и)   из чисел a, b, c меньшим является с, а большим b; к)   среди чисел a, b, c, d есть взаимно противоположные;л)   среди целых чисел a, b, c есть хотя бы два четных; м)   из отрезков с длинами a, b, c можно построить треугольник;
н)   треугольники со сторонами a1, b1, c1
и a2, b2, c2подобны;о)   точка с координатами (x,y) принадлежит внутренней области треугольника
с вершинами A(0,5)

, B(5,0) и C(1,0);п)   точка с координатами (x,y) принадлежит области, внешней по
отношению к треугольнику с вершинами A(0,5), B(1,0) и C(5,0);
р)   четырехугольник со сторонами a, b, c и d является ромбом. [ Ответ ]

7.7. Начертите на плоскости (x,y) область, в которой и только
в которой истинно указанное выражение. Границу, не принадлежащую этой области,
изобразите пунктиром.

[ Ответ ]

7.8. Запишите логическое выражение, которое принимает значение “истина”
тогда и только тогда, когда точка с координатами (x, y) принадлежит заштрихованной
области.

[ Ответ ]

7.9. Пусть a=3, b=5, c=7. Какие значения будут
иметь эти переменные в результате выполнения последовательности операторов:
а)   a:=a 1; b:=a b; c:=a b; a:=sqrt(a)Решение:a=3 1=4, b=4 5=9, c=4 9=13,
a= {корень квадратный из} 4 =2. Ответ:а=2, b=9, c=13; б)   с:=a*b 2; b:=b 1; a:=c-b**2; b:=b*a;в)   b:=b a; c:=c b; b:=1/b*c;г)   p:=c; c:=b; b:=a; a:=p; c:=a*b*c*p;д)   c:=a**(b-3); b:=b-3; a:=(c 1)/2*b; c:=(a b)*a;е)   x:=a; a:=b; b:=c; c:=x; a:

7.10. Задайте с помощью операторов присваивания следующие действия:
а) массив X=(x1, x2) преобразовать по правилу:
в качестве x1 взять сумму, а в качестве х2 — произведение
исходных компонент;

Решение:c:=x[1]:=x[2]; x[2] б) поменять местами значения элементов массива X=(x1, x2);в) в массиве A(N) компоненту с номером i (1<i<N)
заменить полусуммой исходных соседних с нею компонент, соседнюю справа компоненту
заменить на нуль, а соседнюю слева компоненту увеличить на 0.5; г)u = max(x, y, z) min(x-z, y z, y, z);[ Ответ ]

7.11. Задайте с помощью команд если или выбор вычисления
по формулам:

[ Ответ ]

7.12. Постройте графики функций y(x), заданных командами
если:

[ Ответ ]

7.13. Определите значение целочисленной переменной S после выполнения
операторов:

а) S:=128
   нц для i от 1 до 4
      S:=div(S,2)
   кц
Решение

iS
 128
1128/2=64
264/2=32
332/2=16
416/2=8

Ответ: S=8

г) S:=0
   нц для i от 1 до 2
      нц для j от 2 до 3
       S:=S i j
      кц   кц
Решение

ijS
  0
120 1 2=3
 33 1 3=7
227 2 2=11
 311 2 3=16

Ответ: S=16

б)  S:=1; a:=1
    нц для i от 1 до 3
      S:=S i*(i 1)*a
      a:=a 2
    кц
д)нц для i от 1 до 3
       S:=0
       нц для j от 2 до 3
         S:=S i j
       кцкц
в)  S:=1; a:=1
    нц для i от 1 до 3
      S := S i
      нц для j  2 до 3
        S := S j
      кцкц
е)нц для i от 1 до 2
      S := 0
      нц для j  2 до 3
         нц для k  1 до 2
           S := S i j k
         кц  кцкц

[ Ответ ]

7.14. Определите значение переменной S после выполнения операторов:

а)  i:=0; S:=0
    нц пока i<3
      i:=i 1;
      S:=S i*i
    кц
г)  S:=0; N:=125
    нц пока N>0
      S:=S mod(N,10) | S — сумма цифр
      N:=div(N,10)   |     числа N
    кц
Решение

Условие i < 3iS
 00
0 < 3? да10 12=1
1 < 3? да21 22=5
2 < 3? да35 32=14
3 < 3? нет(кц)  

Ответ: S=14

Решение

Условие N > 0SN
 0125
125 > 0? да0 5=512
12 > 0? да5 2=71
1 > 0? да7 1=80
0 > 0? нет (кц)  

Ответ: S=8

б)  S:=0; i:=1
    нц пока i>1
      S:=S 1/i
      i:=i-1
    кц
д)  а:=1; b:=1; S:=0;
    нц пока a<=5
      a:=a b; b:=b a;
      S:=S a b
    кц
в) S:=0; i:=1; j:=5
   нц пока i<j
     S:=S i*j
     i:=i 1
     j:=j-1
   кц
е)  a:=1; b:=1
    нц пока a b<10
      a:=a 1
      b:=b a
    кц
    S:=a b

[ Ответ ]

7.15. Составьте алгоритмы решения задач линейной структуры
(условия этих задач заимствованы из учебного пособия В.М. Заварыкина,
В.Г. Житомирского и М.П. Лапчика “Основы информатики и вычислительной
техники”, 1989):

а)  в треугольнике известны три стороны  a,  b  и  c;
найти (в градусах) углы этого треугольника, используя формулы:

Пояснение.
Обратите внимание на то, что стандартные тригонометрические
функции  
arccosarcsin
 возвращают вычисленное значение
в радианной мере.

Решение:

алг Углы треугольника(арг вещ a,b,c, рез вещ UgolA,UgolB,UgolC)
нач вещ RadGr,UgolARad
    | RadGr — коэф. перевода угла из радианной меры в градусную
    | UgolARad — угол A (в радианах)
  RadGr:=180/3.14
  UgolARad:=ArcCos((b*b c*c-a*a)/(2*b*c))
  UgolA:=UgolARad*RadGr
  UgolB:=ArcSin(b*sin(UgolARad)/a)*RadGr
  UgolC:=180-(UgolA UgolB)
кон

б)  в треугольнике известны две стороны  a,  b  и угол  C
(в радианах) между ними; найти сторону  c,  углы  A  и  B 
(в радианах) и площадь треугольника, используя формулы:

OAP/t1l1.md at master · kolei/OAP · GitHub  
OAP/t1l1.md at master · kolei/OAP · GitHub
OAP/t1l1.md at master · kolei/OAP · GitHub  
с2 = a2 b2 – 2ab cos C.
Пояснение.
Сначала нужно найти сторону  
c
 , а затем остальные
требуемые значения;

в) в треугольнике известны три стороны a, b и c;
найти радиус описанной окружности и угол  A  (в градусах), используя
формулы:

OAP/t1l1.md at master · kolei/OAP · GitHub  
OAP/t1l1.md at master · kolei/OAP · GitHub 
где   OAP/t1l1.md at master · kolei/OAP · GitHub

г) в правильной треугольной пирамиде известны
сторона основания  a  и угол  A  (в градусах) наклона боковой
грани к плоскости основания; найти объем и площадь полной поверхности
пирамиды, используя формулы:

д) в усеченном конусе известны радиусы оснований  R  и  r 
и угол  A  (в радианах) наклона образующей к поверхности большего
основания; найти объем и площадь боковой поверхности конуса, используя формулы:

e)  в правильной четырехугольной пирамиде сторона основания равна
 a , а боковое ребро наклонено к плоскости основания
под углом  A ; найти объем и площадь полной поверхности пирамиды и
площадь сечения, проходящего через вершину пирамиды и диагональ основания
 d ; использовать формулы:

[ Ответ ]

7.16. Составьте алгоритм решения задач развлетвляющейся структуры:

а)  определить, является ли треугольник с заданными сторонами
 a,  b,  c  равнобедренным;
Решение:

алг Треугольник(арг вещ a,b,c, рез лог Otvet)
  дано | a>0, b>0, c>0, a b>c, a c>b, b c>a
  надо | Otvet = да, если треугольник равнобедренный
       | Otvet = нет, если треугольник не равноведренный
нач  если (a=b) или (a=c) или (b=c)
    то Otvet:= да    иначе Otvet:= нет  всекон

б)  определить количество положительных чисел среди заданных
чисел  a,  b  и  c;

в)  меньшее из двух заданных неравных чисел увеличить вдвое,
а большее оставить без изменения;

г)  числа  a  и  b  — катеты одного прямоугольного
треугольника, а  c  и  d  — другого; определить, являются ли
эти треугольники подобными;

д)  даны три точки на плоскости; определить, какая из них ближе к началу координат;

ж)  упорядочить по возрастанию последовательность трех чисел
 a,  b  и  c.
[ Ответ ]

Графический способ записи алгоритмов

Наибольшее распространение благодаря своей наглядности получил графический способ записи алгоритмов. При графическом представлении алгоритм изображается в виде последовательности связанных между собой функциональных блоков, каждый из которых соответствует выполнению одного или нескольких действий.

Такое графическое представление называется схемой алгоритма или блок-схемой. В блок-схеме каждому типу действий (вводу исходных данных, вычислению значений выражений, проверке условий, управлению повторением действий, окончанию обработки и т.п.) соответствует геометрическая фигура, представленная в виде блочного символа.

Блок процесс применяется для обозначения действия или последовательности действий,изменяющих значение, форму представления или размещения данных. Для улучшения наглядности схемы несколько отдельных блоков обработки можно объединять в один блок. Представление отдельных операций достаточно свободно.

Блок решение используется для обозначения переходов управления по условию. В каждом блоке решение должны быть указаны вопрос, условие или сравнение, которые он определяет.

Блок модификация используется для организации циклических конструкций. (Слово модификация означает видоизменение, преобразование). Внутри блока записывается параметр цикла, для которого указываются его начальное значение, граничное условие и шаг изменения значения параметра для каждого повторения.

Блок предопределенный процесс используется для указания обращений к вспомогательным алгоритмам, существующим автономно в виде некоторых самостоятельных модулей, и для обращений к библиотечным подпрограммам.

Блок Ввод-вывод используется для преобразования данных в фор­му, пригодную для обработки (ввод) или отображения результатов обработки (вывод). Отдельным логическим устройствам компьютера или отдельным функциям об­мена соответствуют определенные блочные символы.

Блок Пуск-останов используется для обозначения начала, конца, прерывания процесса обработки данных или выполнения программы.

Блок Документ предназначен для ввода-вывода данных, носителем которых служит бумага.

Общие функции оценки сложности

Сейчас мы перечислим некоторые функции, которые чаще всего используются для вычисления сложности. Функции перечислены в порядке возрастания сложности. Чем выше в этом списке находится функция, тем быстрее будет выполняться алгоритм с такой оценкой.

  1. C – константа (время выполнения алгоритма не зависит от входных параметров, линейные алгоритмы)
  2. log(log(N))
  3. log(N) – (поиск в сортированном массиве)
  4. NC, 0<C<1
  5. N – линейная сложность (поиск в не сортированном массиве)
  6. N*log(N)
  7. NC, C>1
  8. CN, C>1
  9. N!

Если мы хотим оценить сложность алгоритма, уравнение сложности которого содержит несколько этих функций, то уравнение можно сократить до функции, расположенной ниже в таблице. Например, O(log(N) N!)=O(N!).

Если алгоритм вызывается редко и для небольших объёмов данных, то приемлемой можно считать сложность O(N2), если же алгоритм работает в реальном времени, то не всегда достаточно производительности O(N).

Обычно алгоритмы со сложностью N*log(N) работают с хорошей скоростью. Алгоритмы со сложностью NC можно использовать только при небольших значениях C. Вычислительная сложность алгоритмов, порядок которых определяется функциями CN и N! очень велика, поэтому такие алгоритмы могут использоваться только для обработки небольшого объёма данных.

В заключение приведём таблицу, которая показывает, как долго компьютер, осуществляющий миллион операций в секунду, будет выполнять некоторые медленные алгоритмы.

СложностьN=10N=20N=30N=40N=50
N30.001 c0.008 c0.027 c0.064 c0.125 c
2N0.001 c1.05 c17.9 мин1.29 дней35.7 лет
3N0.059 c58.1 мин6.53 лет3.86*105 лет2.28*1010 лет
N!3.63 c7.71*104 лет8.41*1018 лет2.59*1034 лет9.64*1050 лет

Википедия: Временная сложность алгоритма

Понятие алгоритма

Одним из фундаментальных понятий в информатике является понятие алгоритма. Происхождение самого термина «алгоритм» связано с математикой. Это слово происходит от Algorithmi — латинского написания имени Мухаммеда альХорезми (787 — 850), выдающегося математика средневекового Востока. В XII в. был выполнен латинский перевод его математического трактата, из которого европейцы узнали о десятичной позиционной системе счисления и правилах арифметики многозначных чисел.

В наше время понятие алгоритма трактуется шире. Алгоритм — это последовательность команд управления каким-либо исполнителем.

Алгоритм может быть предназначен для выполнения его человеком или автоматическим устройством — формальным исполнителем. Задача исполнителя — точная реализация уже имеющегося алгоритма. Формальный исполнитель не обязан вникать в сущность алгоритма, а возможно, и неспособен его понять.

Примером формального исполнителя может служить автоматическая стиральная машина, которая неукоснительно исполняет предписанные ей действия, даже если вы забыли положить в нее порошок. Человек тоже может выступать в роли формального исполнителя, но в первую очередь формальными исполнителями являются различные автоматические устройства, и компьютер в том числе.

В разделе информатики под названием Программирование изучаются методы программного управления работой ЭВМ. Следовательно, в качестве исполнителя выступает компьютер.

Компьютер работает с величинами — различными информационными объектами: числами, символами, кодами и т.п. Поэтому алгоритмы, предназначенные для управления компьютером, принято называть алгоритмами работы с величинами.

Данные и величины. Совокупность величин, с которыми работает компьютер, принято называть данными. По отношению к программе данные делятся на исходные, результаты (окончательные данные) и промежуточные, которые получаются в процессе вычислений.

Например, при решении квадратного уравнения ах2 Ьх с = 0
исходными данными являются коэффициенты а, Ь, с; результатами — корни уравнения х1, х2; промежуточным данным — дискриминант уравнения D = b2 – 4ас.

Для успешного освоения программирования необходимо усвоить следующее правило: всякая величина занимает свое определенное место в памяти ЭВМ (иногда говорят — ячейку памяти). Хотя термин «ячейка» с точки зрения архитектуры современных ЭВМ несколько устарел, однако в учебных целях его удобно использовать.

У всякой величины имеются три основных свойства: имя, значение и тип (на самом деле многие современные языки, такие как PHP или JS, обходятся без явного указания типа, интерпретируя тип переменной в зависимости от контекста операции).

На уровне команд процессора величина идентифицируется при помощи адреса ячейки памяти, в которой она хранится. В алгоритмах и языках программирования величины делятся на константы и переменные. Константа — неизменная величина, и в алгоритме она представляется собственным значением, например: 15, 34.

7, k, true и т.д. Переменные величины могут изменять свои значения в ходе выполнения программы и представляются символическими именами — идентификаторами, например: X, S2, cod15. Любая константа, как и переменная, занимает ячейку памяти, а значение этих величин определяется двоичным кодом в этой ячейке.

Теперь о типах величин — типах данных. С понятием типа данных вы уже, возможно, встречались, изучая в курсе информатики базы данных и электронные таблицы. Это понятие является фундаментальным для программирования.

В каждом языке программирования существует своя концепция типов данных, своя система типов. Тем не менее в любой язык входит минимально необходимый набор основных типов данных, к которому относятся: целый, вещественный, логический и символьный типы.

ТипЗначенияОперацииВнутреннее представление
ЦелыйЦелые положительные и отрицательные числа в некотором диапазоне.
Примеры: 23, —12, 387
Арифметические операции с целыми числами: , —, *, целое деление и остаток от деления.
Операции отношений (<, >, = и др.)
Формат с фиксированной точкой
ВещественныйЛюбые (целые и дробные) числа в некотором диапазоне.
Примеры: 2.5, -0.01, 45.0, 3.6-109
Арифметические операции: , —, *, /.
Операции отношений
Формат с плавающей точкой
ЛогическийTrue (истина),
False (ложь)
Логические операции: И (&), ИЛИ (|), HE (~). Операции отношений1 бит:
1 – true;
0 – false
СимвольныйЛюбые символы компьютерного алфавита.
Примеры: ‘а’, ‘5’, ‘ ‘, ‘$’
Операции отношенийКоды таблицы символьной кодировки. 1 символ – 1 байт (Сейчас используются многобайтные кодировки: UTF-8, UTF-16…)

Типы констант определяются по контексту (т.е. по форме записи в тексте), а типы переменных устанавливаются в описаниях переменных (не во всех языках; Python, например, не имеет явного определения типа, тип переменной определяетя при первом присваивании).

Есть еще один вариант классификации данных — классификация по структуре. Данные делятся на простые и структурированные. Для простых величин (их еще называют скалярными) справедливо утверждение: одна величина — одно значение, для структурированных: одна величина — множество значений. К структурированным величинам относятся массивы, строки, множества и т.д.

Примеры записи логических выражений, истинных при выполнении
указанных условий.

УсловиеЗапись на школьном алгоритмическом языке
  Дробная часть вещественого числа a равна нулюint(a) = 0
  Целое число a — четноеmod(a, 2) = 0
  Целое число a — нечетноеmod(a, 2) = 1
  Целое число k кратно семиmod(a, 7) = 0
  Каждое из чисел a, b положительно(a>0) и (b>0)
  Только одно из чисел a, b положительно((a>0) и (b<=0)) или
((a<=0) и (b>0))
  Хотя бы одно из чисел a, b, c является отрицательным(a<0) или (b<0) или
(c<0)
  Число x удовлетворяет условию a < x < b (x>a) и (x<b)
  Число x имеет значение в промежутке [1, 3](x>=1) и (x<=3)
  Целые числа a и b имеют одинаковую четность((mod(a, 2)=0) и (mod(b, 2)=0) или
((mod(a, 2)=1) и (mod(b, 2)=1))
  Точка с координатами (x, y) лежит в круге
радиуса r  с центром в точке (a, b)
(x-a)**2 (y-b)**2 < r*r
  Уравнение ax^2 bx c = 0 не имеет действительных корнейb*b - 4*a*c < 0
  Точка (x, y) принадлежит первой или третьей   четверти((x>0) и (y>0)) или
((x<0) и (y>0))
  Точка (x, y) принадлежит внешности единичного
круга   с центром в начале координат или его второй четверти
(x*x y*y > 1) или
((x*x y*y <= 1) и
(x<0) и (y>0))
  Целые числа a и b являются взаимнопротивоположнымиa = -b
  Целые числа a и b являются взаимнообратнымиa*b = 1
  Число a больше среднего арифметического чисел b, c, da > (b c d) / 3
  Число a не меньше среднего геометрического чисел b, c, da >= (b c d) ** (1/3)
  Хотя бы одна из логических переменных F1 и F2 имеет   значение даF1 или F2
  Обе логические переменые F1 и F2 имеют значение даF1 и F2
  Обе логические переменые F1 и F2 имеют значение нетне F1 и не F2
  Логическая переменная F1 имеет значение
да, а   логическая переменная F2 имеет значение нет
F1 и не F2
  Только одна из логических
переменных F1 и F2   имеет значение да
(F1 и не F2) или
(F2 и не F1)

Совет 3. не используйте «магические числа»

Если числа определяют какие-либо статические свойства приложения, то заведите соответствующую константу и применяйте ее. Даже если считаете, что она никогда не изменится (например, число пи, которое, правда, есть в большинстве стандартных библиотек).

Во-первых это упростит вашу задачу, если константа все же изменится. Неожиданно, но такое часто случается! Например, для того же числа пи может измениться необходимая точность. А во-вторых код станет понятнее. Сравните сами, какое выражение проще:
3.

14*radius *radius или
PI *radius *radius?

С другой стороны, в формуле длины окружности
2*Pi *radius создавать константу для двойки необходимости нет. Она имеет смысл лишь в этом контексте.

Существует еще один класс констант. Они не определяют какие-то фундаментальные постоянные, как число пи, а имеют смысл лишь в качестве средства параметризации приложения. Примером выступает размер шрифта или цвет фона главного окна. Большей гибкости можно достичь, если вместо константы в коде использовать переменную, инициализированную по умолчанию значением этой константы.

В результате поведение приложения перестает жестко зависеть от такого параметра. Появляется возможность использовать разные значения в рамках одной и той же программы, что оказывается недостижимым в случае константы. Такой подход позволяет пойти еще дальше и считывать эти параметры из конфигурационных файлов, переходя на новый уровень гибкости.

Совет 4. не пренебрегайте инкапсуляцией

Ключевое слово
private придумано не просто так (хотя, например, в Python его нет).

Скрывайте внутренние особенности реализации модулей. Пренебрежение этим правилом существенно снижает гибкость программы. Если клиенты модуля начинают пользоваться его внутренними особенностями, то возникает зависимость (повышается связность). Любая зависимость — препятствие для внесения изменений.

На самом деле, инкапсуляция работает повсеместно. Правило простое: давайте переменным минимально допустимую область видимости. Если можно, то пусть переменная будет видна только в пределах функции, иначе определите ее в виде
private-поля класса.

Даже уровень доступа
protected создает опасную зависимость (особенно в Java) при том, что его ВСЕГДА можно избежать.

Переменные с
public-доступом и глобальные переменные противоречат принципам ООП (конечно, существуют структуры, но об этом чуть позже).

Следствие из этого совета: избегайте допущений при использовании любого модуля, даже (особенно) если вы сами являетесь его разработчиком. Сегодня функция возвращает упорядоченный набор значений, а завтра нет (когда это не является явным постусловием).

Совет 7. предпочитайте делегирование наследованию

Наследование — статическая связь между классами на этапе компиляции. Любая статика снижает гибкость системы. Проблема заключается в том, что если подкласс реализует определенное поведение, то во время исполнения кода это уже не изменить (либо требуется применение нетривиальных синтаксических структур используемого языка программирования). Альтернативой становится создание классов, поведение которых формируется путем комбинирования более простых компонентов.

Типичный пример заключается в том, что у вас уже есть класс, из которого вы хотите позаимствовать лишь часть свойств при реализации своего класса. Часто это заведомо плохая идея. Например, нередко можно встретить класс на подобии
PersonList, наследующий
List.

Существует очень много причин почему это плохо. Даже не будем вдаваться в подробности, но запомните, что в таких ситуациях лучше либо явно включить существующий класс в виде поля вашего класса, либо использовать
private-наследования в C .

В качестве другого примера вспомним тестовое приложение, которое мы создали при обсуждении потоков в Qt. Для нас было важно обеспечить возможность выбора алгоритма построения фрактала. Мы могли бы реализовать базовый класс приложения, в котором предусмотрели бы виртуальную функцию для построения фрактала.

Тогда для различных алгоритмов нам было бы достаточно унаследовать этот базовый класс, предоставив соответствующие реализации виртуальной функции. Все бы работало, но мы бы не смогли легко перейти от одного алгоритма к другому в процессе работы программы.

Что было сделано на самом деле: алгоритм построения фрактала мы превратили в самостоятельный абстрактный класс. Основная часть приложения использовала экземпляр этого класса в качестве своего поля (не забывайте про совет 1), делегируя ему задачу построения фрактала. Это позволило нам легко совершать подмену алгоритма «на лету». Статическое наследование такой возможности вам не даст.

Да, мы не смогли совсем избежать наследования. Ведь нам нужен полиморфизм. Но мы добавили дополнительный уровень косвенности. Любая косвенность увеличивает гибкость, поскольку создает дополнительную точку сцепления, которую можно подменить в любой момент (как в конструкторе Лего).

Чем больше точек сцепления — тем выше гибкость. Но обратите внимание, что это привело к повышению связности модуля. Теперь если мы захотим повторно использовать какой-либо его уровень в другом проекте, то вместе с ним придется тащить и расположенные ниже слои (либо использовать собственные заглушки, что не упрощает задачу).

Замечу, что рассмотренный пример про алгоритм построения фрактала основан на паттерне Стратегия. Но об этом ниже.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *