29 KiB
Введение
{width="4.60417760279965in" height="5.958333333333333in"}
- О книге
Этот проект задуман как открытое, бесплатное и дружелюбное к новичкам введение в структуры данных и алгоритмы.
-
В книге используются анимационные иллюстрации. Материал изложен ясно и последовательно, что облегчает освоение и помогает начинаю- щим построить «карту знаний» по структурам данных и алгоритмам.
-
Исходный код можно запустить одним кликом, что позволяет трениро- ваться, развивать навыки программирования и формировать понима- ние принципов работы алгоритмов и реализации структур данных на фундаментальном уровне.
-
Мы призываем к взаимопомощи читателей: задавайте вопросы и дели- тесь идеями в комментариях. Обсуждения помогают двигаться вперед всем вместе.
Целевая аудитория
Если вы новичок в алгоритмах, никогда с ними не сталкивались или у вас есть некоторый опыт решения задач, но еще нет четкого понимания структур дан- ных и алгоритмов, эта книга создана специально для вас!
Если у вас уже есть определенный опыт решения задач и вы знакомы с боль- шинством типов задач, эта книга поможет вам освежить и систематизировать знания об алгоритмах. Исходный код может служить набором инструментов для решения задач или алгоритмическим словарем.
Если вы владеете алгоритмами на экспертном уровне, мы будем рады ва- шим ценным советам или совместному участию в создании книги.
Структура книги
Основное содержание книги представлено на рис. 0.1.
- Анализ сложности: критерии и методы оценки структур данных и ал- горитмов. Методы расчета временной и пространственной сложности, распространенные типы, примеры и т. д.
Структуры данных
Массивы и списки
Стек
[и]{.smallcaps} очередь
Хеш- таблицы
Логическая и физическая структура Базовые типы данных
Цифровое и символьное кодирование
Способы непрерывного и распределенного хранения Методы работы, преимущества
[и]{.smallcaps} недостатки двух способов
Реализация списка на основе динамического массива
Память и кеш в компьютере
Последний пришел -- первый вышел, первый пришел -- первый вышел, двусторонняя очередь
Реализация на основе массива и связного списка
Принцип работы хеш-таблицы, реализация на основе массива
Хеш-коллизии, цепная и открытая адресация Назначение и цели хеш-алгоритмов
Идеальное, совершенное, полное, сбалансированное
двоичное дерево
Анализ сложности
Итерация и рекурсия
Временная сложность
Пространственная сложность
Поиск
Циклы for и while, вложенные циклы
Стек вызовов рекурсии, хвостовая рекурсия, дерево рекурсии
Сравнение итерации и рекурсии
Асимптотическая верхняя граница
Методы вычисления, основные типы
Наихудшая, наилучшая, средняя временная сложность
Методы вычисления, основные типы Компромисс между временем
и пространством
Перебор: линейный поиск, поиск в ширину и глубину
Адаптивный поиск: двоичный поиск, хеш-поиск, поиск по дереву
Выбор алгоритма поиска
Местность, устойчивость, адаптивность, основанность на сравнении
Перебор: сортировка выбором, пузырьком, вставками
Деревья
Куча
Графы
https://github.com/krahets/hello-algo
Представление связным списком и массивом, сравнение Обход в ширину; прямой, симметричный и обратный порядок Двоичное дерево поиска
АВЛ-дерево
Минимальная и максимальная куча, Алгоритмы
очередь с приоритетом
Реализация кучи на основе массива, операция построения кучи
Задача о k наибольших элементов
Ориентированный, связный и взвешенный графы Список и матрица смежности, их сравнение Обход в ширину и в глубину
Сортировка
Разделяй и властвуй
Поиск
с возвратом
Динамическое программирование
Жадные алгоритмы
«Разделяй и властвуй»: быстрая сортировка, сортировка слиянием, пирамидальная сортировка
Без сравнения: блочная сортировка,
сортировка подсчетом, поразрядная сортировка Стратегия «разделяй и властвуй»
Примеры задач: двоичный поиск, построение дерева, Ханойская башня
Задача поиска с возвратом, каркас кода
Примеры задач: перестановки, сумма подмножеств, n ферзей
Перебор, рекурсия с мемоизацией, восходящая рекурсия
Перекрывающиеся подзадачи, оптимальная подструктура, отсутствие последействия
Методы определения задач динамического программирования, этапы решения
Примеры задач: рюкзак 0-1, полный рюкзак, расстояние редактирования
Характеристики жадных задач, этапы решения
Примеры задач: дробный рюкзак, максимальная вместимость, максимальное произведение разбиения
0.1. О книге ❖ 13
-
Структуры данных: классификация основных типов данных и структур данных. Определение, преимущества и недостатки, основные операции, распространенные типы, типичные приложения и методы реализации мас- сивов, списков, стеков, очередей, хеш-таблиц, деревьев, куч, графов и т. д.
-
Алгоритмы: определение, преимущества и недостатки, эффективность, области применения, этапы решения и примеры задач для поиска, со- ртировки, алгоритма «разделяй и властвуй», обратного поиска, динами- ческого программирования, жадных алгоритмов и т. д.
Благодарности
Эта книга постоянно совершенствуется благодаря совместным усилиям множества участников открытого сообщества. Благодарим каждого автора, вложившего свое время и силы. Имена перечислены в порядке, автоматически сгенерированном GitHub: krahets, coderonion, Gonglja, nuomi1, Reanon, justin-tse, hpstory, danielsss, curtishd, night-cruise, S-N-O-R-L-A-X, msk397, gvenusleo, khoaxuantu, RiverTwilight, rongyi, gyt95, zhuoqinyue, K3v123, Zuoxun, mingXta, hello-ikun, FangYuan33, GN-Yu, yuelinxin, longsizhuo, Cathay-Chen, guowei-gong, xBLACKICEx, IsChristina, JoseHu- ng, qualifier1024, QiLOL, pengchzn, Guanngxu, L-Super, WSL0809, Slone123c, lhxsm, yuan0221, what-is-me, theNefelibatas, longranger2, cy-by-side, xiongsp, Jefferson- Huang, Transmigration-zhou, magentaqin, Wonderdch, malone6, xiaomiusa87, gaofer, bluebean-cloud, a16su, Shyam-Chen, nanlei, hongyun-robot, Phoenix0415, MolDuM, Nigh, he-weilai, junminhong, mgisr, iron-irax, yd-j, XiaChuerwu, XC-Zero, seven1240, SamJin98, wodray, reeswell, NI-SW, Horbin-Magician, Enlightenus, xjr7670, YangXu- anyi, DullSword, boloboloda, iStig, qq909244296, jiaxianhua, wenjianmin, keshida, kilikilikid, lclc6, lwbaptx, liuxjerry, lucaswangdev, lyl625760, hts0000, gledfish, fbigm, echo1937, szu17dmy, dshlstarr, Yucao-cy, coderlef, czruby, bongbongbakudan, beinten- tional, ZongYangL, ZhongYuuu, luluxia, xb534, bitsmi, ElaBosak233, baagod, zhouLion, yishangzhang, yi427, yabo083, weibk, wangwang105, th1nk3r-ing, tao363, 4yDX3906, syd168, steventimes, sslmj2020, smilelsb, siqyka, selear, sdshaoda, Xi-Row, popozhu, nuquist19, noobcodemaker, XiaoK29, chadyi, ZhongGuanbin, shanghai-Jerry, JackYang- hellobobo, Javesun99, lipusheng, BlindTerran, ShiMaRing, FreddieLi, FloranceYeh, iF- leey, fanchenggang, gltianwen, goerll, Dr-XYZ, nedchu, curly210102, CuB3y0nd, KraHsu, CarrotDLaw, youshaoXG, bubble9um, fanenr, eagleanurag, LifeGoesOnionOnionOnion, 52coder, foursevenlove, KorsChen, hezhizhen, linzeyan, ZJKung, GaochaoZhu, hopk- ings2008, yang-le, Evilrabbit520, Turing-1024-Lee, thomasq0, Suremotoo, Allen-Scai, Risuntsy, Richard-Zhang1019, qingpeng9802, primexiao, nidhoggfgg, 1ch0, MwumLi, martinx, ZnYang2018, hugtyftg, logan-qiu, psychelzh, Keynman, KeiichiKasai и 0130w. Рецензирование кода книги выполнили coderonion, curtishd, Gonglja, gve- nusleo, hpstory, justin-tse, khoaxuantu, krahets, night-cruise, nuomi1, Reanon и ron- gyi (в алфавитном порядке). Благодарим их за потраченное время и усилия, ко-
торые обеспечили стандартизацию и единообразие кода на различных языках.
В процессе создания этой книги мне помогало много людей.
-
Благодарю моего наставника в компании, доктора Ли Си (Li Xi), который в одной из бесед вдохновил меня «действовать быстро», что укрепило мою решимость написать эту книгу.
-
Благодарю мою девушку Паo Пао (Pao Pao), которая, будучи первым чи- тателем книги, дала множество ценных советов с точки зрения новичка в алгоритмах, что сделало книгу более понятной и доступной.
-
Благодарю Тен Бао (Teng Bao), Ци Бао (Qi Bao) и Фей Бао (Fei Bao) за креа- тивное название книги, которое навевает приятные воспоминания о на- писании первой строки кода «Hello World!».
-
Благодарю Сяо Цюань (Xiao Quan) за профессиональную помощь в во- просах интеллектуальной собственности, что сыграло важную роль в со- вершенствовании этой открытой книги.
-
Благодарю Су Тун (Su Tong) за дизайн обложки и логотипа книги, а также за терпение при многократных исправлениях по моим просьбам.
-
Благодарю @squidfunk за советы по оформлению и за разработку от- крытой темы документации Material-for-MkDocs.
В процессе написания я ознакомился с множеством учебников и статей по структурам данных и алгоритмам. Эти работы послужили отличным образцом для этой книги, обеспечив ее точность и качество. Выражаю благодарность всем преподавателям и предшественникам за их выдающийся вклад!
Настоящая книга пропагандирует метод обучения, сочетающий умственную и практическую деятельность, на который меня вдохновила книга Dive into Deep Learning («Погружение в глубокое обучение», на англ. языке). Настоятель- но рекомендую эту замечательную работу всем читателям.
Сердечно благодарю своих родителей, ведь именно ваша постоянная поддержка и ободрение дали мне возможность заняться этим увлека- тельным делом.
как использовать эту книгу
Стиль изложения
-
Главы, имеющие символ * после заголовка, являются дополнительными и содержат более сложный материал. Если у вас ограничено время, мож- но их пропустить.
-
Профессиональные термины выделяются полужирным шрифтом (в печат- ной и PDF-версии) или подчеркиванием (в веб-версии), например массив (array). Рекомендуется запоминать их для удобства чтения литературы.
-
Важные моменты и обобщающие фразы выделяются полужирным шрифтом, на такие тексты следует обращать особое внимание.
-
При упоминании терминов, различающихся в разных языках програм- мирования, в качестве стандарта используется Python, например None для обозначения «пустого значения».
-
В некоторых местах книга отходит от стандартов комментирования про- граммного кода ради более компактного оформления. Комментарии де- лятся на три типа: заголовочные, содержательные и многострочные.
""" Заголовочные комментарии, используются для обозначения функций, классов, тестовых примеров и т.д. """
# Содержательные комментарии, используются для пояснения кода.
"""
Многострочные комментарии. """
Эффективное обучение с помощью анимированных иллюстраций
Видео и изображения обладают более высокой плотностью информации и структурированностью по сравнению с текстом, что облегчает понимание. В этой книге ключевые и сложные моменты в основном представлены в виде анимированных иллюстраций, а текстовая информация служит по- яснением и дополнением.
Если какой-либо раздел в книге сопровождается анимационной иллюстра- цией, как на рис. 0.2, используйте иллюстрацию в качестве основного ис- точника информации, а текст -- в качестве вспомогательного.
{width="5.06667760279965in" height="3.4239577865266844in"}
Рис. 0.2. Пример анимационной иллюстрации. Шаг 1
{width="5.066665573053369in" height="3.4239577865266844in"}
Рис. 0.2. Продолжение. Шаги 2--3
{width="5.066674321959755in" height="3.4239577865266844in"}
Рис. 0.2. Окончание. Шаги 4--5
Углубление понимания через практику написания кода
Сопроводительный код размещен в репозитории GitHub, он содержит тесто- вые примеры и может быть запущен одним нажатием кнопки, как по- казано на рис. 0.3.
{width="5.0666863517060365in" height="3.4239577865266844in"}
Рис. 0.3. Запуск примера кода
Если позволяет время, рекомендуется самостоятельно набирать код. Если время ограничено, по крайней мере просмотрите и выполните весь код.
Процесс написания кода приносит больше пользы, чем его чтение. Настоя- щее обучение -- это обучение на практике.
Предварительная подготовка для запуска кода включает три этапа.
-
Установка локальной среды программирования. Следуйте инструк- циям программы установки. Если среда уже установлена, этот шаг мож- но пропустить.
-
Клонирование или загрузка репозитория кода. Перейдите в репози- торий GitHub. Если у вас установлена утилита Git, можно клонировать репозиторий с помощью следующей команды:
git clone https://github.com/krahets/hello-algo.git
Либо можно нажать кнопку Download ZIP (Скачать ZIP-архив), как показа- но на рис. 0.4, загрузить архив с кодом и затем распаковать его на локальном компьютере.
Рис. 0.4. Клонирование репозитория и загрузка кода
- Запуск исходного кода. Если для блока кода в книге указано имя фай- ла, этот файл можно найти в папке codes репозитория, как показано на рис. 0.5. Исходный код можно запустить одним нажатием, что поможет вам сэкономить время на отладку и сосредоточиться на изучении ма- териала.
Рис. 0.5. Блоки кода и соответствующие файлы исходного кода
Помимо локального запуска, в веб-версии книги код на Python можно выполнить в визуальной среде (реализовано на основе pythontutor). Для этого нажмите кнопку Визуализировать выполнение под блоком кода, как показано на рис. 0.6. Также в раскрывшемся окне можно нажать кнопку От- крыть в полноэкранном режиме для более удобного просмотра1.
{width="5.122829177602799in" height="3.12in"}
Рис. 0.6. Визуальное выполнение кода Python
Совместное развитие через вопросы и обсуждения
При чтении книги не оставляйте без внимания непонятные моменты. Мы при- зываем вас задавать вопросы в разделе комментариев, и я вместе с колле- гами постараюсь ответить вам в течение двух дней.
В конце каждой главы веб-версии книги предусмотрено место для коммен- тариев, как показано на рис. 0.7. Рекомендуется уделять внимание содержимо- му этой области. С одной стороны, это позволит вам понять, с какими пробле- мами сталкиваются другие читатели, что поможет выявить пробелы в знаниях и стимулировать более глубокое понимание. С другой стороны, мы надеемся, что вы будете отвечать на вопросы других участников и делиться своими мне- ниями.
1 Функция визуального выполнения кода доступна только в китайской веб-версии книги -- Прим. перев.
{width="5.066666666666666in" height="3.4239577865266844in"}
Рис. 0.7. Пример раздела комментариев
Дорожная карта изучения алгоритмов
Процесс изучения структур данных и алгоритмов можно разделить на три этапа.
-
Введение в алгоритмы. Необходимо ознакомиться с особенностями и применением различных структур данных, изучить принципы, про- цессы, назначение и эффективность различных алгоритмов.
-
Решение алгоритмических задач. Рекомендуется начинать с популяр- ных задач и решить не менее 100 из них, чтобы познакомиться с основ- ными алгоритмическими проблемами. При первом решении задач вы можете столкнуться с так называемым забвением знаний -- не беспокой- тесь, это нормально. Следуйте при повторении задач кривой забывания Эббингауза, обычно после 3--5 циклов повторения они хорошо запоми- наются. Рекомендуемые списки задач и планы решения можно найти в этом репозитории GitHub.
-
Построение системы знаний. В процессе обучения можно читать статьи по алгоритмам, изучать типичные решения и учебники по алгоритмам, чтобы постоянно обогащать систему знаний. В решении задач можно при- менять продвинутые стратегии, такие как классификация по темам, множе- ственные решения одной задачи или одно решение для множества задач. Советы по этим техникам обучения можно найти в различных сообществах.
Эта книга в основном охватывает первый этап и призвана помочь вам эф- фективно подготовиться ко второму и третьему этапам обучения, как показа- но на рис. 0.8.
- Резюме ❖ 23
Базовые сведения
Этап 2
Тренировка навыков
Этап 3
Построение системы знаний
Решение алгоритмических задач
Периодическое повторение Повторное решение одной и той же задачи через определенное время
для формирования долговременной памяти и углубления понимания
Активное обобщение Систематизация содержа- ния, выявление законо-
мерностей для построения целостной системы знаний
резюме
Рис. 0.8. Дорожная карта изучения алгоритмов
-
Основная аудитория книги -- новички в изучении алгоритмов. Если у вас уже есть определенная база, книга поможет систематизировать имею- щиеся знания об алгоритмах, а исходный код послужит инструменталь- ной библиотекой для решения задач.
-
Содержание книги включает три основные части -- анализ сложности, структуры данных и алгоритмы -- и охватывает большинство тем в этой области.
-
Для новичков в алгоритмах крайне важно изучить начальные разделы книги, чтобы избежать множества ошибок в будущем.
-
Анимированные иллюстрации в книге обычно используются для пред- ставления ключевых и сложных аспектов. При чтении книги следует уде- лять этим материалам большое внимание.
-
Практика -- лучший способ изучения программирования. Настоятельно рекомендуется запускать исходный код и самостоятельно писать про- граммы.
-
В веб-версии книги каждая глава имеет область комментариев, где вы можете задавать вопросы и делиться своим мнением.
Глава 1







