Программирование • 26 ноября 2024 • 5 мин чтения

Что такое алгоритмы и какими они бывают

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

Что такое алгоритм

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

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

1. Запросить у пользователя два числа.
2. Сложить эти числа.
3. Вывести результат на экран.

Так можно реализовать этот алгоритм на Python:
num1 = int(input("Введите первое число: "))
num2 = int(input("Введите второе число: "))
sum = num1 + num2
print("Сумма чисел", num1, "и", num2, "равна", sum)

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

Для чего нужны алгоритмы и кто их использует

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

Рассмотрим примеры использования алгоритмов специалистами в сфере IT. 

  • Программисты. Любой код, даже самый простой, — это алгоритм, с помощью которого можно структурировать задачи и разбить их на понятные для компьютера этапы. По сути, разработчик перекладывает на компьютер действия, которые может выполнить сам, в виде алгоритмов, но программа выполняет их быстрее и точнее.
  • Data Scientists. Они используют алгоритмы для анализа данных, выявления закономерностей и построения моделей. Например, с их помощью специалист может классифицировать информацию, определив типы клиентов компании, и спрогнозировать их отток.
  • DevOps-инженеры. Они работают внутри цикла разработки продуктов, который основан на методологии DevOps (от англ. development — «разработка» и operations — «администрирование»). Такие специалисты помогают настроить взаимодействие членов команды, создать единую инфраструктуру и автоматизировать процессы.
По сути, методология DevOps — это алгоритм действий команды проекта
  • Тестировщики. Они проверяют продукт на наличие ошибок, разрабатывая алгоритмы тестирования. Их цель — найти правильные и неправильные кейсы использования программы, составить отчёт об ошибках и передать его разработчикам.
  • Менеджеры проектов. Например, при работе по методологии Scrum проджект-менеджер следит за тем, чтобы команда придерживалась алгоритма работы: соблюдает сроки спринтов, собирает правки от заказчика и согласовывает очередную версию продукта.
  • Менеджеры по продажам. Скрипты и воронка продаж — это тоже алгоритмы, по которым ведутся переговоры с потенциальными клиентами. В них прописаны последовательные действия и аргументы, которые позволят достичь результата — заключения сделки.

Основные свойства алгоритмов

Вне зависимости от сферы применения алгоритмы должны соответствовать определённым свойствам: 

  • Конечность. Алгоритм должен приводить к конкретному результату, то есть завершаться. Например, программа в итоге решает поставленную задачу, а врач — помогает пациенту излечиться. Исключение — специально созданные бесконечные алгоритмы, в которых не заложена результативность. Например, они используются в играх, когда игрок ничего не делает, но вокруг ходят NPC (неигровые персонажи), летают птицы и плывут облака. По сути, в этот момент выполняется бесконечный алгоритм. 
  • Предсказуемость. Это свойство предполагает, что при одинаковых условиях алгоритм приводит к одинаковому результату. К примеру, при расчёте площади треугольника со сторонами по 3, 4 и 5 см он всегда должен возвращать 6 см2. Это свойство даёт возможность применять алгоритм к разным данным и понимать, что он решит эту задачу верно. А если в нём есть ошибка, он может выдать неожиданный результат. Чем выше сложность алгоритма, тем более критичными могут быть последствия. Был случай, когда ошибка в работе аппарата для лучевой терапии привела к тому, что люди получили повышенную долю радиации, в 8 раз превышающую норму. 
  • Дискретность. Алгоритм должен разделяться на более мелкие алгоритмы, каждый из которых должен приносить определённый результат. Это гарантирует, что общая задача будет решена верно. По сути, вычисление высокой сложности можно разложить на последовательность элементарных арифметических операций, которые известны компьютеру. Согласно концепции MapReduce, разработанной Google, любая обработка данных может быть разделена на три базовых действия: filter, map и reduce. 
  • Понятность. Алгоритм должен быть описан так, чтобы его понял исполнитель. Допустим, следуя этому свойству, код программы должен быть понятен компьютеру, а инструкция по сборке мебели — покупателю. В противном случае возникнет ошибка и алгоритм не будет выполнен, то есть код не сработает, а мебель не будет собрана. 
  • Определённость. Важно, чтобы алгоритм был чётким и однозначным. Проще говоря, у последовательности действий не должно быть разночтений, они должны пониматься одинаково вне зависимости от исполнителей, условий или данных.

Виды алгоритмов

Существует четыре базовых вида алгоритмов, которые соотносятся с элементами структурного программирования:

1. Линейный — последовательный алгоритм, шаги которого идут чётко друг за другом. Этот вид не предполагает внешних изменений условий и повторений. Возьмём для примера приготовление бутерброда с сыром и маслом. Если пропустить шаг «Нарезать хлеб» или «Намазать масло», он не выполнится.
По линейному алгоритму считаются простые формулы. Например, расчёт площади трапеции:

def calculate_trapezoid_area():
# Ввод данных
a = float(input("Введите длину первого основания (a): "))
b = float(input("Введите длину второго основания (b): "))
h = float(input("Введите высоту (h): "))

# Разбиение формулы на шаги
# Шаг 1: Сложение оснований
сумма_оснований = a + b

# Шаг 2: Умножение на высоту
произведение = сумма_оснований * h

# Шаг 3: Деление на 2
площадь_трапеции = произведение / 2

# Вывод результата
print(f"Площадь трапеции: {площадь_трапеции}")

2. Ветвящийся — предполагает изменение условий по принципу «если…, то…». Проще говоря, выбор шагов происходит в зависимости от выполнения или невыполнения условия. Например, при поиске самого большого значения из пары чисел алгоритм работает следующим образом: если первое число больше второго, то переменной присваивается значение первого числа, если оно меньше — значение второго.

Так выглядит алгоритм для перехода улицы в разных странах:

def cross_street(country):
# Функция для перехода пешеходного перехода в зависимости от страны.

if country == 'Россия':
print("Посмотрите налево и направо, переходите на зелёный свет.")
elif country == 'США':
print("Посмотрите налево и направо, переходите на зелёный свет.")
elif country == 'Великобритания':
print("Посмотрите направо и налево, переходите на зелёный свет.")
else:
print("Информация о правилах перехода для этой страны недоступна.")

3. Циклический — повторяется множество раз, пока условие не выполнится или не станет ложным. Например, простой алгоритм поиска в списке выглядит как повторяющееся сравнение очередного элемента с искомым. При этом если элемент найден или список закончился — алгоритм завершается.

Пример на языке Python.
def linear_search(lst, target):
for index, element in enumerate(lst):
if element == target:
return index
return -1

4. Рекурсивный — алгоритм, который вызывает сам себя при определённых условиях. Пример: проверка слова-палиндрома, которое читается одинаково в любом направлении. Если первая и последняя буква одинаковые, алгоритм повторно запускается, чтобы проверить следующие символы с начала и конца слова:

def is_palindrome_recursive(s):
if len(s) <= 1:
return True
# Проверяем первый и последний символы на равенство
if s[0] != s[-1]:
return False
# Рекурсивный вызов без первого и последнего символов
return is_palindrome_recursive(s[1:-1])

В зависимости от задачи к одним и тем же данным можно применять разные виды алгоритмов

Примеры алгоритмов

Рассмотрим примеры практического применения алгоритмов в программировании.

Алгоритм для решения квадратного уравнения.

import math

# Ввод коэффициентов:
a = float(input("Введите коэффициент a: "))
b = float(input("Введите коэффициент b: "))
c = float(input("Введите коэффициент c: "))

# Определение дискриминанта:
D = b**2 - 4*a*c

# Анализ дискриминанта, определение корней:
if D > 0:
x1 = (-b + math.sqrt(D)) / (2*a)
x2 = (-b - math.sqrt(D)) / (2*a)
print(f"В уравнении есть два различных действительных корня: x1 = {x1}, x2 = {x2}")
elif D == 0:
x = -b / (2*a)
print(f"В уравнении есть один действительный корень: x = {x}")
else:
print("В уравнении нет действительных корней.")

Алгоритм, подсчитывающий статистику в группах с помощью действий filter — map — reduce.

const people = [
{ name: 'Alice', age: 22 },
{ name: 'Bob', age: 17 },
{ name: 'Charlie', age: 25 },
{ name: 'David', age: 15 },
{ name: 'Eve', age: 30 }
];

// Шаг 1. Отфильтруем людей старше 18 лет:
const adults = people.filter(person => person.age > 18);

// Шаг 2. Преобразуем их имена в заглавные буквы:
const uppercaseNames = adults.map(person => person.name.toUpperCase());

// Шаг 3. Посчитаем общую длину всех имён:
const totalNameLength = uppercaseNames.reduce((total, name) => total + name.length, 0);

console.log(totalNameLength); // Вывод: 14 (ALICE, CHARLIE, EVE)

Совет эксперта

Пётр Кушнир
Если человек интересуется разработкой, прежде чем приступать к освоению языков программирования, полезно изучить алгоритмы. Это связано с тем, что у разных языков есть свои особенности, но по сути свойства и виды алгоритмов у всех одинаковые. В свою очередь, изучение алгоритмов стоит начать с блок-схем, которые можно встретить в обычной жизни, например в тестах или инструкциях. Это позволит быстрее понять алгоритмы и подойти к освоению языков программирования с минимальной базой.
Статью подготовили:
Пётр Кушнир
Яндекс Практикум
Автор курса «Java-разработчик»
Женя Соловьёва
Яндекс Практикум
Редактор
Полина Овчинникова
Яндекс Практикум
Иллюстратор

Дайджест блога: ежемесячная подборка лучших статей от редакции

Поделиться
Идеи новогодних подарков от нейросети + промокоды на курсы Практикума и акции от партнеров
Tue Nov 26 2024 14:24:57 GMT+0300 (Moscow Standard Time)