This commit is contained in:
krahets
2026-03-30 08:17:41 +08:00
parent 68cafe99dd
commit 46bccf0065
484 changed files with 60193 additions and 20315 deletions
+38 -38
View File
@@ -65,8 +65,8 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Noto Sans";--md-code-font:"JetBrains Mono"}</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Sans:300,300i,400,400i,500,500i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"PT Sans";--md-code-font:"JetBrains Mono"}</style>
@@ -574,7 +574,7 @@
<span class="md-ellipsis">
Глава 1. Знакомство с алгоритмами
Глава 1. Введение в алгоритмы
@@ -596,7 +596,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 1. Знакомство с алгоритмами
Глава 1. Введение в алгоритмы
</label>
@@ -646,7 +646,7 @@
<span class="md-ellipsis">
1.2 Что такое структуры данных и алгоритмы
1.2 Что такое алгоритм
@@ -1181,7 +1181,7 @@
<span class="md-ellipsis">
Глава 4. Массив и связный список
Глава 4. Массивы и списки
@@ -1203,7 +1203,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 4. Массив и связный список
Глава 4. Массивы и списки
</label>
@@ -1309,7 +1309,7 @@
<span class="md-ellipsis">
4.4 Память и кеш *
4.4 Оперативная память и кэш *
@@ -1591,7 +1591,7 @@
<span class="md-ellipsis">
Глава 6. Хеширование
Глава 6. Хеш-таблицы
@@ -1613,7 +1613,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 6. Хеширование
Глава 6. Хеш-таблицы
</label>
@@ -1691,7 +1691,7 @@
<span class="md-ellipsis">
6.3 Хеш-алгоритмы
6.3 Алгоритмы хеширования
@@ -1788,7 +1788,7 @@
<span class="md-ellipsis">
Глава 7. Дерево
Глава 7. Деревья
@@ -1810,7 +1810,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 7. Дерево
Глава 7. Деревья
</label>
@@ -2058,7 +2058,7 @@
<span class="md-ellipsis">
7.3 Представление дерева массивом
7.3 Представление двоичного дерева массивом
@@ -2142,7 +2142,7 @@
<span class="md-ellipsis">
7.6 Резюме
7.6 Краткие итоги
@@ -2305,7 +2305,7 @@
<span class="md-ellipsis">
8.3 Задача Top-K
8.3 Задача Top-k
@@ -2396,7 +2396,7 @@
<span class="md-ellipsis">
Глава 9. Граф
Глава 9. Графы
@@ -2418,7 +2418,7 @@
<span class="md-nav__icon md-icon"></span>
Глава 9. Граф
Глава 9. Графы
</label>
@@ -2468,7 +2468,7 @@
<span class="md-ellipsis">
9.2 Базовые операции над графами
9.2 Базовые операции графа
@@ -2524,7 +2524,7 @@
<span class="md-ellipsis">
9.4 Резюме
9.4 Краткие итоги
@@ -2663,7 +2663,7 @@
<span class="md-ellipsis">
10.2 Точка вставки двоичного поиска
10.2 Двоичный поиск точки вставки
@@ -2691,7 +2691,7 @@
<span class="md-ellipsis">
10.3 Граничные случаи двоичного поиска
10.3 Двоичный поиск границ
@@ -2719,7 +2719,7 @@
<span class="md-ellipsis">
10.4 Стратегия оптимизации через хеширование
10.4 Стратегии оптимизации хеширования
@@ -2747,7 +2747,7 @@
<span class="md-ellipsis">
10.5 Алгоритмы поиска: новый взгляд
10.5 Переосмысление алгоритмов поиска
@@ -2952,7 +2952,7 @@
<span class="md-ellipsis">
11.3 Пузырьковая сортировка
11.3 Сортировка пузырьком
@@ -2980,7 +2980,7 @@
<span class="md-ellipsis">
11.4 Сортировка вставкой
11.4 Сортировка вставками
@@ -3285,7 +3285,7 @@
<span class="md-ellipsis">
12.1 Алгоритмы разделяй и властвуй
12.1 Стратегия разделяй и властвуй
@@ -3313,7 +3313,7 @@
<span class="md-ellipsis">
12.2 Стратегия поиска разделяй и властвуй
12.2 Поисковая стратегия разделяй и властвуй
@@ -3590,7 +3590,7 @@
<span class="md-ellipsis">
13.4 Задача о $n$ ферзях
13.4 Задача о n ферзях
@@ -3731,7 +3731,7 @@
<span class="md-ellipsis">
14.1 Введение в динамическое программирование
14.1 Первое знакомство с динамическим программированием
@@ -3843,7 +3843,7 @@
<span class="md-ellipsis">
14.5 Задача о неограниченном рюкзаке
14.5 Задача о полном рюкзаке
@@ -4555,7 +4555,7 @@
<!-- Page content -->
<h1 id="71">7.1 &nbsp; Двоичное дерево<a class="headerlink" href="#71" title="Permanent link">&para;</a></h1>
<p><u>Двоичное дерево (binary tree)</u> - это нелинейная структура данных, представляющая отношения порождения между "предками" и "потомками" и отражающая логику "разделения надвое". Подобно связному списку, базовой единицей двоичного дерева является узел; каждый узел содержит значение, ссылку на левого дочернего узла и ссылку на правого дочернего узла.</p>
<p><u>Двоичное дерево (binary tree)</u> - это нелинейная структура данных, представляющая отношения между "предками" и "потомками" и отражающая логику "разделяй и властвуй". Подобно связному списку, базовой единицей двоичного дерева является узел; каждый узел содержит значение, ссылку на левого дочернего узла и ссылку на правого дочернего узла.</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:13"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><input id="__tabbed_1_6" name="__tabbed_1" type="radio" /><input id="__tabbed_1_7" name="__tabbed_1" type="radio" /><input id="__tabbed_1_8" name="__tabbed_1" type="radio" /><input id="__tabbed_1_9" name="__tabbed_1" type="radio" /><input id="__tabbed_1_10" name="__tabbed_1" type="radio" /><input id="__tabbed_1_11" name="__tabbed_1" type="radio" /><input id="__tabbed_1_12" name="__tabbed_1" type="radio" /><input id="__tabbed_1_13" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">Python</label><label for="__tabbed_1_2">C++</label><label for="__tabbed_1_3">Java</label><label for="__tabbed_1_4">C#</label><label for="__tabbed_1_5">Go</label><label for="__tabbed_1_6">Swift</label><label for="__tabbed_1_7">JS</label><label for="__tabbed_1_8">TS</label><label for="__tabbed_1_9">Dart</label><label for="__tabbed_1_10">Rust</label><label for="__tabbed_1_11">C</label><label for="__tabbed_1_12">Kotlin</label><label for="__tabbed_1_13">Ruby</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
@@ -4734,7 +4734,7 @@
</div>
</div>
<p>Каждый узел имеет две ссылки (указателя), которые соответственно указывают на <u>левого дочернего узла (left-child node)</u> и <u>правого дочернего узла (right-child node)</u>; данный узел называется <u>родительским узлом (parent node)</u> для этих двух дочерних узлов. Если задан некоторый узел двоичного дерева, то дерево, образованное его левым дочерним узлом и всеми узлами ниже него, называется <u>левым поддеревом (left subtree)</u> этого узла; аналогично определяется <u>правое поддерево (right subtree)</u>.</p>
<p><strong>В двоичном дереве, кроме листовых узлов, все остальные узлы содержат дочерние узлы и непустые поддеревья</strong>. Как показано на рисунке 7-1, если рассматривать "узел 2" как родительский, то его левым и правым дочерними узлами будут "узел 4" и "узел 5"; левое поддерево - это "узел 4 и дерево ниже него", а правое поддерево - это "узел 5 и дерево ниже него".</p>
<p><strong>Узлы, не имеющие дочерних узлов, называют листьями, а все остальные узлы содержат дочерние узлы и непустые поддеревья</strong>. Как показано на рисунке 7-1, если рассматривать "узел 2" как родительский, то его левым и правым дочерними узлами будут "узел 4" и "узел 5"; левое поддерево - это "узел 4 и дерево ниже него", а правое поддерево - это "узел 5 и дерево ниже него".</p>
<p><img alt="Родительский узел, дочерние узлы и поддеревья" class="animation-figure" src="../binary_tree.assets/binary_tree_definition.png" /></p>
<p align="center"> Рисунок 7-1 &nbsp; Родительский узел, дочерние узлы и поддеревья </p>
@@ -4755,7 +4755,7 @@
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Обрати внимание: обычно под "высотой" и "глубиной" понимают "число пройденных ребер", но в некоторых задачах или учебниках их могут определять как "число пройденных узлов". В таком случае и высоту, и глубину нужно увеличить на 1 .</p>
<p>Обычно под "высотой" и "глубиной" понимают "число пройденных ребер", но в некоторых задачах или учебниках их могут определять как "число пройденных узлов". В таком случае и высоту, и глубину нужно увеличить на 1 .</p>
</div>
<h2 id="712">7.1.2 &nbsp; Базовые операции двоичного дерева<a class="headerlink" href="#712" title="Permanent link">&para;</a></h2>
<h3 id="1">1. &nbsp; Инициализация двоичного дерева<a class="headerlink" href="#1" title="Permanent link">&para;</a></h3>
@@ -5104,20 +5104,20 @@
</details>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Обрати внимание: вставка узла может изменить исходную логическую структуру двоичного дерева, а удаление узла обычно означает удаление этого узла вместе со всеми его поддеревьями. Поэтому в двоичном дереве операции вставки и удаления обычно являются частью более крупного набора операций, который и реализует осмысленное действие.</p>
<p>Стоит помнить, что вставка узла может изменить исходную логическую структуру двоичного дерева, а удаление узла обычно означает удаление этого узла вместе со всеми его поддеревьями. Поэтому в двоичном дереве операции вставки и удаления обычно являются частью более крупного набора операций, который и реализует осмысленное действие.</p>
</div>
<h2 id="713">7.1.3 &nbsp; Распространенные типы двоичных деревьев<a class="headerlink" href="#713" title="Permanent link">&para;</a></h2>
<h3 id="1_1">1. &nbsp; Идеальное двоичное дерево<a class="headerlink" href="#1_1" title="Permanent link">&para;</a></h3>
<p>Как показано на рисунке 7-4, <u>идеальное двоичное дерево (perfect binary tree)</u> полностью заполнено на всех уровнях. В идеальном двоичном дереве степень листовых узлов равна <span class="arithmatex">\(0\)</span> , а у всех остальных узлов степень равна <span class="arithmatex">\(2\)</span> ; если высота дерева равна <span class="arithmatex">\(h\)</span> , то общее число узлов равно <span class="arithmatex">\(2^{h+1} - 1\)</span> , что образует стандартную экспоненциальную зависимость и отражает часто встречающееся в природе явление клеточного деления.</p>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Обрати внимание: в китайскоязычном сообществе идеальное двоичное дерево часто называют <u>полностью заполненным двоичным деревом</u>.</p>
<p>В китайскоязычном сообществе идеальное двоичное дерево часто называют <u>полностью заполненным двоичным деревом</u>.</p>
</div>
<p><img alt="Идеальное двоичное дерево" class="animation-figure" src="../binary_tree.assets/perfect_binary_tree.png" /></p>
<p align="center"> Рисунок 7-4 &nbsp; Идеальное двоичное дерево </p>
<h3 id="2_1">2. &nbsp; Полное двоичное дерево<a class="headerlink" href="#2_1" title="Permanent link">&para;</a></h3>
<p>Как показано на рисунке 7-5, <u>полное двоичное дерево (complete binary tree)</u> допускает неполное заполнение только на самом нижнем уровне, причем узлы этого уровня должны непрерывно заполняться слева направо. Обрати внимание: идеальное двоичное дерево тоже является полным двоичным деревом.</p>
<p>Как показано на рисунке 7-5, <u>полное двоичное дерево (complete binary tree)</u> допускает неполное заполнение только на самом нижнем уровне, причем узлы этого уровня должны непрерывно заполняться слева направо. Стоит отметить, что идеальное двоичное дерево тоже является полным двоичным деревом.</p>
<p><img alt="Полное двоичное дерево" class="animation-figure" src="../binary_tree.assets/complete_binary_tree.png" /></p>
<p align="center"> Рисунок 7-5 &nbsp; Полное двоичное дерево </p>
@@ -5134,7 +5134,7 @@
<h2 id="714">7.1.4 &nbsp; Вырождение двоичного дерева<a class="headerlink" href="#714" title="Permanent link">&para;</a></h2>
<p>На рисунке 7-8 показаны идеальная структура двоичного дерева и вырожденная структура. Когда каждый уровень двоичного дерева полностью заполнен узлами, мы получаем "идеальное двоичное дерево"; когда же все узлы смещаются к одной стороне, двоичное дерево вырождается в "связный список".</p>
<ul>
<li>Идеальное двоичное дерево соответствует лучшему случаю и позволяет полностью раскрыть преимущества двоичного дерева с точки зрения "разделяй и властвуй".</li>
<li>Идеальное двоичное дерево соответствует лучшему случаю и позволяет в полной мере раскрыть преимущества подхода "разделяй и властвуй".</li>
<li>Связный список представляет противоположную крайность: все операции становятся линейными, а временная сложность деградирует до <span class="arithmatex">\(O(n)\)</span> .</li>
</ul>
<p><img alt="Лучший и худший случаи структуры двоичного дерева" class="animation-figure" src="../binary_tree.assets/binary_tree_best_worst_cases.png" /></p>