mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-16 00:46:06 +00:00
build
This commit is contained in:
@@ -19,7 +19,7 @@ comments: true
|
||||
|
||||
### 1. Поиск узла
|
||||
|
||||
Для заданного целевого значения узла `num` можно выполнить поиск, опираясь на свойства двоичного дерева поиска. Как показано на рисунках ниже, мы объявляем узел `cur` , стартуем от корня дерева `root` и циклически сравниваем значения `cur.val` и `num` .
|
||||
Для заданного целевого значения узла `num` можно выполнить поиск, опираясь на свойства двоичного дерева поиска. Как показано на рисунке 7-17, мы объявляем узел `cur` , стартуем от корня дерева `root` и циклически сравниваем значения `cur.val` и `num` .
|
||||
|
||||
- Если `cur.val < num` , это означает, что целевой узел находится в правом поддереве `cur` , поэтому выполняем `cur = cur.right` .
|
||||
- Если `cur.val > num` , это означает, что целевой узел находится в левом поддереве `cur` , поэтому выполняем `cur = cur.left` .
|
||||
@@ -345,7 +345,7 @@ comments: true
|
||||
|
||||
### 2. Вставка узла
|
||||
|
||||
Пусть дан элемент `num` , который нужно вставить. Чтобы сохранить свойство двоичного дерева поиска "левое поддерево < корень < правое поддерево", процесс вставки выглядит следующим образом.
|
||||
Пусть дан элемент `num` , который нужно вставить. Чтобы сохранить свойство двоичного дерева поиска «левое поддерево < корень < правое поддерево», процесс вставки показан на рисунке 7-18.
|
||||
|
||||
1. **Найти позицию для вставки**: как и в операции поиска, начиная от корня, мы циклически спускаемся вниз в зависимости от соотношения между текущим значением узла и `num` , пока не выйдем за листовой узел (то есть не дойдем до `None` ).
|
||||
2. **Вставить узел в найденную позицию**: инициализировать узел `num` и поставить его на место этого `None` .
|
||||
@@ -811,7 +811,7 @@ comments: true
|
||||
|
||||
### 3. Удаление узла
|
||||
|
||||
Сначала нужно найти в двоичном дереве целевой узел, а затем удалить его. Как и при вставке, после удаления необходимо сохранить свойство двоичного дерева поиска: "левое поддерево < корень < правое поддерево". Поэтому в зависимости от числа дочерних узлов у удаляемого узла, то есть для случаев со степенью 0, 1 и 2, выполняются разные операции удаления.
|
||||
Сначала нужно найти в двоичном дереве целевой узел, а затем удалить его. Как и при вставке, после удаления необходимо сохранить свойство двоичного дерева поиска: «левое поддерево < корень < правое поддерево». Поэтому в зависимости от числа дочерних узлов у удаляемого узла, то есть для случаев со степенью 0, 1 и 2, выполняются разные операции удаления.
|
||||
|
||||
Как показано на рисунке 7-19, когда степень удаляемого узла равна $0$ , это значит, что узел является листом и может быть удален напрямую.
|
||||
|
||||
@@ -825,11 +825,11 @@ comments: true
|
||||
|
||||
<p align="center"> Рисунок 7-20 Удаление узла в двоичном дереве поиска (степень 1) </p>
|
||||
|
||||
Когда степень удаляемого узла равна $2$ , мы уже не можем удалить его напрямую и должны использовать для замены другой узел. Чтобы сохранить свойство двоичного дерева поиска "левое поддерево $<$ корень $<$ правое поддерево", **этим узлом может быть минимальный узел правого поддерева или максимальный узел левого поддерева**.
|
||||
Когда степень удаляемого узла равна $2$ , мы уже не можем удалить его напрямую и должны использовать для замены другой узел. Чтобы сохранить свойство двоичного дерева поиска «левое поддерево $<$ корень $<$ правое поддерево», **этим узлом может быть минимальный узел правого поддерева или максимальный узел левого поддерева**.
|
||||
|
||||
Предположим, мы выбираем минимальный узел правого поддерева, то есть следующий узел в симметричном обходе. Тогда процесс удаления выглядит так.
|
||||
Предположим, мы выбираем минимальный узел правого поддерева, то есть следующий узел в симметричном обходе. Тогда процесс удаления показан на рисунке 7-21.
|
||||
|
||||
1. Найти следующий узел в "последовательности симметричного обхода" для удаляемого узла и обозначить его как `tmp` .
|
||||
1. Найти следующий узел в «последовательности симметричного обхода» для удаляемого узла и обозначить его как `tmp` .
|
||||
2. Значением `tmp` перезаписать значение удаляемого узла, а затем рекурсивно удалить узел `tmp` из дерева.
|
||||
|
||||
=== "<1>"
|
||||
@@ -1595,7 +1595,7 @@ comments: true
|
||||
|
||||
### 4. Упорядоченность симметричного обхода
|
||||
|
||||
Как показано на рисунке 7-22, симметричный обход двоичного дерева следует порядку "лево $\rightarrow$ корень $\rightarrow$ право", а двоичное дерево поиска удовлетворяет соотношению "левый дочерний узел $<$ корень $<$ правый дочерний узел".
|
||||
Как показано на рисунке 7-22, симметричный обход двоичного дерева следует порядку «лево $\rightarrow$ корень $\rightarrow$ право», а двоичное дерево поиска удовлетворяет соотношению «левый дочерний узел $<$ корень $<$ правый дочерний узел».
|
||||
|
||||
Это означает, что при симметричном обходе двоичного дерева поиска мы всегда сначала будем посещать следующий минимальный узел, и отсюда получается важное свойство: **последовательность симметричного обхода двоичного дерева поиска является возрастающей**.
|
||||
|
||||
@@ -1607,7 +1607,7 @@ comments: true
|
||||
|
||||
## 7.4.2 Эффективность двоичного дерева поиска
|
||||
|
||||
Для заданного набора данных можно рассмотреть хранение либо в массиве, либо в двоичном дереве поиска. Из таблицы ниже видно, что временная сложность операций двоичного дерева поиска имеет логарифмический порядок и обеспечивает стабильную высокую производительность. Только в сценариях с очень частыми вставками и редкими поисками и удалениями массив может быть эффективнее, чем двоичное дерево поиска.
|
||||
Для заданного набора данных можно рассмотреть хранение либо в массиве, либо в двоичном дереве поиска. Как видно по данным в таблице 7-2, временная сложность операций двоичного дерева поиска имеет логарифмический порядок и обеспечивает стабильную высокую производительность. Только в сценариях с очень частыми вставками и редкими поисками и удалениями массив может быть эффективнее, чем двоичное дерево поиска.
|
||||
|
||||
<p align="center"> Таблица 7-2 Сравнение эффективности массива и дерева поиска </p>
|
||||
|
||||
@@ -1621,7 +1621,7 @@ comments: true
|
||||
|
||||
</div>
|
||||
|
||||
В идеальном случае двоичное дерево поиска является "сбалансированным", и тогда любой узел можно найти за $\log n$ итераций.
|
||||
В идеальном случае двоичное дерево поиска является «сбалансированным», и тогда любой узел можно найти за $\log n$ итераций.
|
||||
|
||||
Однако если в двоичное дерево поиска непрерывно вставлять и удалять узлы, оно может выродиться в связный список, как показано на рисунке 7-23. Тогда временная сложность различных операций тоже вырождается до $O(n)$ .
|
||||
|
||||
|
||||
Reference in New Issue
Block a user