Вот лишь краткое изложение идеи:
В BST левое поддерево узла T
содержит только элементы, меньшие, чем значение, хранящееся в T
. Если k
меньше, чем количество элементов в левом поддереве, k
наименьший элемент должен принадлежать левому поддереву. В противном случае, если k
больше, то k
наименьший элемент находится в правом поддереве.
Мы можем дополнить BST, чтобы каждый узел в нем сохранял количество элементов в своем левом поддереве (предположим, что левое поддерево данного узла включает этот узел). С помощью этой части информации легко пройти по дереву, неоднократно запрашивая количество элементов в левом поддереве, чтобы решить, делать ли рекурсию в левое или правое поддерево.
Теперь предположим, что мы находимся в узле T:
- Если k == num_elements (левое поддерево T) , то ответ, который мы ищем, - это значение в node
T
.
- Если k> num_elements (левое поддерево T) , то, очевидно, мы можем игнорировать левое поддерево, потому что эти элементы также будут меньше
k
th наименьшего. Итак, мы сводим задачу к поиску k - num_elements(left subtree of T)
наименьшего элемента правого поддерева.
- Если k <num_elements (левое поддерево T) , то
k
наименьший по k
размеру элемент находится где-то в левом поддереве, поэтому мы сводим проблему к поиску th наименьшего элемента в левом поддереве.
Анализ сложности:
Это требует O(depth of node)
времени, что O(log n)
в худшем случае для сбалансированного BST или O(log n)
в среднем для случайного BST.
Для BST требуется O(n)
хранилище, а O(n)
для хранения информации о количестве элементов требуется другое . Все операции BST требуют O(depth of node)
времени, и требуется O(depth of node)
дополнительное время для поддержания информации о «количестве элементов» для вставки, удаления или вращения узлов. Следовательно, хранение информации о количестве элементов в левом поддереве сохраняет пространственную и временную сложность BST.