Изменения

Перейти к: навигация, поиск

Дерево поиска, наивная реализация

237 байт добавлено, 22:13, 24 мая 2015
м
Нет описания правки
* <tex>\mathrm{postorderTraversal}</tex> {{---}} обход узлов в порядке: левое поддерево, правое поддерево, вершина
inorderTraversal('''Node''' x)
'''if''' x != ''null''
inorderTraversal(x.left)
'''print''' x.key
Корректность данного алгоритма следует из свойств бинарного дерева поиска.
preorderTraversal('''Node''' x)
'''if''' x != ''null''
'''print''' x.key
preorderTraversal(x.left)
preorderTraversal(x.right)
postfixTraversalpostorderTraversal('''Node''' x) '''if''' x != ''null''
postorderTraversal(x.left)
postorderTraversal(x.right)
Данные алгоритмы выполняют обход за время <tex>O(n)</tex>, поскольку процедура вызывается ровно два раза для каждого узла дерева.
=== Поиск элемента ===
[[Файл:Bst search.png|thumb|right|318px|Поиск элемента 4]]
Для поиска элемента в бинарном дереве поиска можно воспользоваться следующей процедурой, которая принимает в качестве параметров корень дерева и искомый ключ. Для каждого узла функция сравнивает значение его ключа с искомым ключом. Если ключи одинаковы, то функция возвращает текущий узел, в противном случае функция вызывается рекурсивно для левого или правого поддерева. Узлы, которые посещает функция образуют нисходящий путь от корня, так что время ее работы <tex>O(h)</tex>, где <tex>h</tex> {{---}} высота дерева.
'''Node''' search('''Node''' x, '''key''' k)
'''if''' x == ''null '' '''or''' k == x.key
'''return''' x
'''if''' k < x.key
Чтобы найти минимальный элемент в бинарном дереве поиска, необходимо просто следовать указателям <tex>left</tex> от корня дерева, пока не встретится значение <tex>null</tex>. Если у вершины есть левое поддерево, то по свойству бинарного дерева поиска в нем хранятся все элементы с меньшим ключом. Если его нет, значит эта вершина и есть минимальная. Аналогично ищется и максимальный элемент. Для этого нужно следовать правым указателям.
'''Node''' minimum('''Node''' x)
'''if''' x.left == ''null''
'''return''' x
'''return''' minimum(x.left)
'''Node''' maximum('''Node''' x)
'''if''' x.right == ''null''
'''return''' x
'''return''' maximum(x.right)
Если у узла есть правое поддерево, то следующий за ним элемент будет минимальным элементом в этом поддереве. Если у него нет правого поддерева, то нужно следовать вверх, пока не встретим узел, который является левым дочерним узлом своего родителя. Поиск предыдущего выполнятся аналогично. Если у узла есть левое поддерево, то следующий за ним элемент будет максимальным элементом в этом поддереве. Если у него нет левого поддерева, то нужно следовать вверх, пока не встретим узел, который является правым дочерним узлом своего родителя.
'''Node''' next('''Node''' x)
'''if''' x.right != ''null''
'''return''' minimum(x.right)
y = x.parent
'''while''' y != ''null '' '''and''' x == y.right
x = y
y = y.parent
'''Node''' prev('''Node''' x)
'''if''' x.left != ''null''
'''return''' maximum(x.left)
y = x.parent
'''while''' y != ''null '' '''and''' x == y.left
x = y
y = y.parent
Если у узла есть правое поддерево, то следующий за ним элемент будет минимальным элементом в этом поддереве. Если у него нет правого поддерева, то начнем поиск от корня. Спускаемся вниз по дереву. Если значение узла больше значения в рассматриваемом в данный момент узле, перейдем в правое поддерево, иначе перейдем в левое поддерево. Аналогично выполняется поиск предыдущего элемента. Рекурсивные реализации обеих функций:
'''Node''' next('''Node''' x, '''Node''' t) <font color="green">// x - элемент, для которого ищем следующий, t - текущее поддерево</font>
'''if''' t != ''null''
'''Node''' successor = next(x, t.left)
'''if''' successor == ''null''
'''if''' t.key > x.key
'''return''' t
'''return''' successor
'''return''' next(x, t.right)
'''return''''' null''
'''Node''' prev('''Node''' x, '''Node''' t) <font color="green">// x - элемент, для которого ищем предыдущий, t - текущее поддерево</font>
'''if''' t != ''null''
'''Node''' ancestor = prev(x, t.right)
'''if''' ancestor == ''null''
'''if''' t.key <= x.key
'''return''' t
'''return''' ancestor
'''return''' prev(x, t.left)
'''return''''' null''
Обе операции выполняются за время <tex>O(h)</tex>.
=== Вставка ===
insert('''Node''' x, '''Node''' z) <font color="green">// x - корень поддерева, z - вставляемый элемент</font>
'''if''' z.key > x.key
'''if''' x.right != ''null''
insert(x.right, z)
'''else'''
z.parent = x; x.right = z;
'''else'''
'''if''' x.left != ''null''
insert(x.left, z)
'''else'''
z.parent = x; x.left = z;
Время работы алгоритма {{---}} <tex>O(h)</tex>.
delete('''Node''' root, '''Node''' z) <font color="green">// корень поддерева, удаляемый элемент</font>
'''Node''' x, y <font color="green">// x - элемент, который нужно поместить вместо y</font>
'''if''' z.left != ''null '' '''and''' z.right != ''null '' <font color="green">// если z имеет двух детей</font>
y = '''next'''(z) <font color="green">// y - элемент, следующий за удаляемым, x - null</font>
x = ''null''
'''if''' y == y.parent.left
y.parent.left = ''null''
'''else'''
y.parent.right = ''null''
z.key = y.key <font color="green">// подвешиваем y вместо z</font>
z.data = y.data
'''else if''' z.left != ''null '' '''or''' z.right != ''null '' <font color="green">// eсли z имеет одного ребенка</font>
y = z <font color="green">// y - удаляемый элемент</font>
'''if''' y.left != ''null '' <font color="green">// x - ребенок y</font>
x = y.left
'''else'''
'''else''' <font color="green">// если z не имеет детей</font>
y = z <font color="green">// y - удаляемый элемент, x - null</font>
x = ''null'' '''if''' x != ''null '' <font color="green">// подвешиваем x вместо y</font>
x.parent = y.parent
'''if''' y.parent == ''null''
root = x
'''else'''
Рекурсивная функция, возвращающая дерево с удаленным элементом <tex>z</tex>:
'''Node''' delete('''Node''' root, '''Node''' z) <font color="green">// корень поддерева, удаляемый элемент</font>
'''if''' root == ''null''
'''return''' root
'''if''' z.key < root.key
'''else if''' z.key > root.key
root.right = remove(root.right, z)
'''else if''' root.left != ''null '' '''and''' root.right != ''null''
root.key = minimum(root.right).key
root.right = remove(root, root.right)
'''else'''
'''if''' root.left != ''null''
root = t.left
'''else'''
* [[Поисковые структуры данных]]
* [[Рандомизированное бинарное дерево поиска]]
* [[Красно-черное дерево]]
==Источники информации==
[[Категория: Деревья поиска]]
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Структуры данных]]
188
правок

Навигация