Files
hello-algo/ru/chapters/chapter_01.md
2026-03-25 16:54:42 +08:00

170 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Введение в алгоритмы
![](ru/docs/assets/media/image50.jpeg){width="3.8117727471566054in" height="4.595624453193351in"}
#### Алгоритмы повсюду
> Говоря об алгоритмах, естественно вспомнить о математике. Однако на самом деле многие алгоритмы не связаны со сложной математикой, а больше полага- ются на базовую логику, которая повсеместно встречается в нашей повседнев- ной жизни.
>
> Прежде чем углубиться в обсуждение алгоритмов, стоит упомянуть интерес- ный факт: **вы уже точно освоили множество алгоритмов и привыкли при- менять их в повседневной жизни**. Далее приведем несколько конкретных примеров, чтобы подтвердить этот факт.
>
> **Пример 1**: **поиск в словаре**. В словаре все слова упорядочены по алфавиту. Предположим, нам нужно найти слово, начинающееся на букву «r». Обычно для этого нужно выполнить следующие действия (см. рис. 1.1):
1) открыть словарь примерно на половине страниц и посмотреть, какая буква является первой на этой странице, -- предположим, это буква «m»;
2) поскольку в алфавите буква «r» идет после «m», исключаем первую по- ловину словаря, и область поиска сужается до второй половины;
3) продолжаем повторять шаги 1 и 2, пока не найдем страницу, где первой буквой слов будет «r».
![](ru/docs/assets/media/image52.jpeg)
> **Рис. 1.1.** Этапы поиска в словаре. Шаг 1
>
> ![](ru/docs/assets/media/image54.jpeg)
![](ru/docs/assets/media/image56.jpeg)
> **Рис. 1.1.** *Продолжение*. Шаги 2--3
>
> ![](ru/docs/assets/media/image58.jpeg)
![](ru/docs/assets/media/image60.jpeg)
> **Рис. 1.1.** *Окончание*. Шаги 4--5
>
> Навык поиска в словаре, которым владеет каждый школьник, на самом деле является известным алгоритмом двоичного поиска. С точки зрения структуры данных словарь можно рассматривать как отсортированный массив. С точки зрения алгоритма последовательность операций по поиску в словаре можно считать двоичным поиском.
>
> **Пример 2**: **упорядочивание карт**. Во время игры в карты необходимо каж- дый раз упорядочивать карты в руке от меньшего к большему. Для этого нужно выполнить следующие действия (см. рис. 1.2):
1) разделить карты на упорядоченную и неупорядоченную части, предпо- лагая, что изначально самая левая карта уже упорядочена;
2) из неупорядоченной части извлечь одну карту и вставить ее в правиль- ное место в упорядоченной части. После этого две самые левые карты станут упорядоченными;
3) ![](ru/docs/assets/media/image62.jpeg)повторять шаг 2, каждый раз перемещая одну карту из неупорядоченной части в упорядоченную, пока все карты не станут упорядоченными.
> **Рис. 1.2.** Этапы упорядочивания карт
>
> Метод упорядочивания карт по своей сути является алгоритмом сортиров- ки вставками, который весьма эффективен при обработке небольших наборов данных. Многие функции сортировки в библиотеках программирования ис- пользуют именно этот алгоритм.
>
> **Пример 3**: **сдача**. Предположим, что в супермаркете мы купили товар стои- мостью 69 руб. и дали кассиру купюру в 100 руб. Кассир должен вернуть нам 31 руб. Для этого ему нужно выполнить действия, показанные на рис. 1.3.
1. Варианты выбора -- это купюры номиналом меньше 31 руб. Пусть у нас имеются номиналы 1, 5, 10 и 20 руб.
2. Взять самую крупную доступную купюру в 20 руб. Остаток сдачи соста- вит 31 20 = 11 руб.
3. Взять самую крупную из оставшихся купюр в 10 руб. Остаток составит 11 10 = 1 руб.
4. Взять самую крупную из оставшихся купюр в 1 руб. Остаток составит 1 1 = 0 руб.
5. Завершить выдачу сдачи, схема: 20 + 10 + 1 = 31 руб.
![](ru/docs/assets/media/image64.jpeg)
> **Рис. 1.3.** Этапы выдачи сдачи
>
> В этих шагах мы на каждом этапе выбираем наилучший вариант (используя купюры наибольшего номинала), в итоге получая оптимальную схему сдачи. С точки зрения структуры данных и алгоритмов этот метод по своей сути яв- ляется жадным алгоритмом.
>
> От приготовления блюда до межзвездных путешествий решение практи- чески любой задачи неразрывно связано с алгоритмами. Появление компью- теров позволило нам с помощью программирования хранить структуры дан- ных в памяти, а также писать код для вызовов к центральному и графическому процессору для выполнения алгоритмов. Таким образом, мы можем перено- сить задачи из реальной жизни в компьютер, решая различные сложные про- блемы более эффективно.
#### что такое алгоритм
1. **Определение алгоритма**
> *Алгоритм* -- это набор инструкций или шагов, предназначенных для решения конкретной задачи за ограниченное время, обладающий следующими свой- ствами:
1) задача четко определена, включает ясные определения входных и вы- ходных данных;
2) обладает осуществимостью, может быть выполнен за ограниченное ко- личество шагов, времени и памяти;
3) каждый шаг имеет определенное значение, при одинаковых входных данных и условиях выполнения результат всегда будет одинаковым.
### Определение структуры данных
> *Структура данных* -- это способ организации и хранения данных, включающий содержимое данных, их взаимосвязи и методы операций с ними. Структура данных преследует следующие цели:
1) минимизацию занимаемого пространства для экономии памяти ком- пьютера;
2) максимально быструю обработку данных, включая доступ, добавление, удаление и обновление данных;
3) обеспечение простого представления данных и логической информации для эффективного выполнения алгоритмов.
> **Проектирование структуры данных** -- **это процесс, полный компромис- сов**. Если вы хотите улучшить один аспект, часто приходится идти на уступки в другом. Приведем два примера.
1. Связный список, по сравнению с массивом, более удобен для добавления и удаления данных, но имеет проблемы со скоростью доступа к данным.
2. Граф, по сравнению со связным списком, предоставляет более богатую логическую информацию, но требует большего объема памяти.
### Взаимосвязь структур данных и алгоритмов
> Структуры данных и алгоритмы тесно взаимосвязаны, что проявляется в сле- дующих трех аспектах (см. рис. 1.4):
1) структуры данных являются основой алгоритмов. Они обеспечивают структурированное хранение данных и методы их обработки;
2) алгоритмы оживляют структуры данных. Сами по себе структуры дан- ных лишь хранят информацию, но в сочетании с алгоритмами они по- зволяют решать конкретные задачи;
3) алгоритмы можно реализовать на основе различных структур данных, однако эффективность их выполнения может значительно различаться. Поэтому выбор подходящей структуры данных является ключевым факто- ром.
<!-- -->
2. Что такое алгоритм ❖ **31**
![](ru/docs/assets/media/image66.jpeg)
> **Рис. 1.4.** Взаимосвязь структур данных и алгоритмов
>
> Структуры данных и алгоритмы подобны конструктору, как показано на рис. 1.5. Комплект конструктора, помимо множества деталей, содержит так- же подробную инструкцию по сборке. Следуя этой инструкции шаг за шагом, можно собрать красивую модель.
![](ru/docs/assets/media/image67.jpeg){width="5.09092738407699in" height="3.15in"}
> **Рис. 1.5.** Сборка конструктора
>
> Подробное описание аналогии с конструктором представлено в табл. 1.1.
>
> **Таблица 1.1.** Сравнение структур данных и алгоритмов с конструктором
>
> **Структуры данных и алгоритмы Конструктор**
>
> Входные данные Несобранные детали конструктора
>
> Структура данных Организация деталей конструктора, включая фор- му, размер, способы соединения и т. д.
>
> Алгоритм Последовательность действий по сборке деталей в целевую модель
>
> Выходные данные Собранная модель конструктора
>
> Стоит отметить, что структуры данных и алгоритмы не зависят от языка программирования. Именно поэтому данная книга предлагает их реализации на различных языках.
#### резюме
- Алгоритмы повсеместно присутствуют в нашей повседневной жизни и не являются недосягаемыми сложными знаниями. На самом деле мы уже освоили множество алгоритмов, которые помогают решать различ- ные жизненные задачи.
- Принцип поиска в словаре соответствует алгоритму двоичного поис- ка. Бинарный поиск иллюстрирует важную идею алгоритмов «разделяй и властвуй».
- Процесс сортировки карт в колоде очень похож на алгоритм сортировки вставками, который хорошо подходит для сортировки небольших набо- ров данных.
- Процесс размена валюты по своей сути является жадным алгоритмом, в котором на каждом этапе принимается наилучшее на данный момент решение.
- Алгоритм представляет собой набор инструкций или шагов, предназна- ченных для решения конкретной задачи в ограниченное время, а струк- тура данных -- это способ организации и хранения данных в компьютере.
- Структуры данных и алгоритмы тесно связаны. Структуры данных явля- ются основой для алгоритмов, а алгоритмы оживляют структуры данных.
- Структуры данных и алгоритмы можно сравнить с конструктором: де- тали конструктора представляют данные, их форма и способы соедине- ния -- структуры данных, а этапы сборки конструктора соответствуют алгоритмам.
### Вопросы и ответы
> 1.3. Резюме ❖ **33**
>
> **Вопрос**. Я программист, и я никогда не использовал алгоритмы для решения задач в своей повседневной работе, поскольку часто используемые алгорит- мы уже встроены в языки программирования и их можно использовать на- прямую. Означает ли это, что задачи, с которыми мы сталкиваемся на работе, не требуют применения алгоритмов?
>
> **Ответ**. Если сравнить конкретные профессиональные навыки с приемами в боевых искусствах, то базовые дисциплины скорее напоминают «внутрен- нюю силу».
>
> Я считаю, что изучение алгоритмов (и других базовых дисциплин) важно не для того, чтобы реализовывать их с нуля в работе, а для того, чтобы на осно- ве полученных знаний принимать профессиональные решения и оценки при решении задач, тем самым повышая общее качество работы. Простой пример: каждый язык программирования имеет встроенные функции сортировки.
>
> Если бы мы не изучали структуры данных и алгоритмы, то, получив любые данные, мы, возможно, просто передали бы их этой функции сортировки. Все работает гладко, производительность хорошая, и на первый взгляд проблем нет. Однако если мы изучили алгоритмы, то знаем, что временная сложность встроенной функции сортировки составляет *O*(*n* log *n*). Если же данные пред- ставлены целыми числами фиксированной разрядности (например, номерами студентов), то можно использовать более эффективный метод поразрядной сортировки, снизив временную сложность до *O*(*nk*), где *k* -- это количество раз- рядов. При больших объемах данных экономия времени выполнения может привести к значительным преимуществам, таким как снижение затрат и улуч-
>
> шение пользовательского опыта.
>
> В инженерной практике множество задач трудно решить оптимальным об- разом, и многие из них решаются «как-то». Сложность задачи зависит как от ее природы, так и от уровня знаний и опыта человека, который ее анализирует. Чем более полными знаниями и большим опытом обладает человек, тем глубже он может проанализировать проблему и тем изящнее может быть ее решение.
>
> Глава 2