- •Б‑деревья
- •Производительность б‑деревьев
- •Вставка элементов в б‑дерево
- •Удаление элементов из б‑дерева
- •Разновидности б‑деревьев
- •Нисходящие б‑деревья
- •Улучшение производительности б‑деревьев
- •Балансировка для устранения разбиения блоков
- •Добавление свободного пространства
- •Вопросы, связанные с обращением к диску
- •Псевдоуказатели
- •Выбор размера блока
- •Кэширование узлов
Б‑деревья
Б‑деревья (B‑trees) являются другой формой сбалансированных деревьев, немного более наглядной, чем АВЛ‑деревья. Каждый узел в Б‑дереве может содержать несколько ключей данных и несколько указателей на дочерние узлы. Поскольку каждый узел содержит несколько элементов, такие узлы иногда называются блоками.
=======171
@Рис. 7.14. Программа AVL
Между каждой парой соседних указателей находится ключ, который можно использовать для определения ветви, по которой нужно следовать при вставке или поиске элемента. Например, в дереве, показанном на рис. 7.15, корневой узел содержит два ключа: G и R. Чтобы найти элемент со значением, которое идет перед G, нужно искать в первой ветви. Чтобы найти элемент, имеющий значение между G и R, проверяется вторая ветвь. Чтобы найти элемент, который следует за R, выбирается третья ветвь.
Б‑дерево порядка K обладает следующими свойствами:
Каждый узел содержит не более 2 * K ключей.
Каждый узел, кроме может быть корневого, содержит не менее K ключей.
Внутренний узел, имеющий M ключей, имеет M + 1 дочерних узлов.
Все листья дерева находятся на одном уровне.
Б‑дерево на рис. 7.15 имеет 2 порядок. Каждый узел может иметь до 4 ключей. Каждый узел, кроме может быть корневого, должен иметь не менее двух ключей. Для удобства, узлы Б‑дерева обычно имеют четное число ключей, поэтому порядок дерева обычно является целым числом.
Выполнение требования, чтобы каждый узел Бдерева порядка K содержал от K до 2 * K ключей, поддерживает дерево сбалансированным. Так как каждый узел должен иметь не менее K ключей, он должен при этом иметь не менее K + 1 дочерних узлов, поэтому дерево не может стать слишком высоким и тонким. Наибольшая высота Б‑дерева, содержащего N узлов, может быть равна O(logK+1(N)). Это означает, что сложность алгоритма поиска в таком дереве порядка O(log(N)). Хотя это и не так очевидно, операции вставки и удаления элемента из Б‑дерева также имеют сложность порядка O(log(N)).
@Рис. 7.15. Б‑дерево
=======172
Производительность б‑деревьев
Применение Б‑деревьев особенно полезно при разработке больших приложений, работающих с базами данных. При достаточно большом порядке Б‑дерева, любой элемент в дереве можно найти после проверки всего нескольких узлов. Например, высота Б‑дерева 10 порядка, содержащего миллион записей, не может быть больше log11(1.000.000), или выше шести уровней. Чтобы найти определенный элемент, потребуется проверить не более шести узлов.
Сбалансированное двоичное дерево с миллионом элементов имело бы высоту log2(1.000.000), или около 20. Тем не менее, узлы двоичного дерева содержат всего по одному ключевому значению. Для поиска элемента в двоичном дереве, пришлось бы проверить 20 узлов и 20 значений. Для поиска элемента в Б‑дереве пришлось бы проверить 5 узлов и 100 ключей.
Применение Б‑деревьев может обеспечить более высокую скорость работы, если проверка ключей выполняется относительно просто, в отличие от проверки узлов. Например, если база данных находится на диске, чтение данных с диска может происходить достаточно медленно. Когда же данные находятся в памяти, их проверка может происходить очень быстро.
Чтение данных с диска происходит большими блоками, и считывание целого блока занимает столько же времени, сколько и чтение одного байта. Если узлы Б‑дерева не слишком велики, то чтение узла Б‑дерева с диска займет не больше времени, чем чтение узла двоичного дерева. В этом случае, для поиска 5 узлов в Б‑дереве потребуется выполнить 5 медленных обращений к диску, плюс 100 быстрых обращений к памяти. Поиск 20 узлов в двоичном дереве потребует 20 медленных обращений к диску и 20 быстрых обращений к памяти, при этом поиск в двоичном дереве будет более медленным, поскольку время, затраченное на 15 лишних обращений к диску будет намного больше, чем сэкономленное время 80 обращений к памяти. Вопросы, связанные с обращением к диску, позднее обсуждаются в этой главе более подробно.