2. Порядковые деревья
Порядковым называется красно-черное
дерево, каждая вершина которого, помимо
обычной информации имеет поле в котором
хранится размер поддерева (не считая NULL-
листьев) с корнем в x (size).
Считая что размер поддерева листа равен 0
можно написать следующее соотношение:
x->size = x->left->size + x->right->size +1
4. Порядковые деревья
void OTRank(root, x){
r = x->left->size+1;
y = x;
while (y!=root){
if(y==y->parent->right);
r=r + y->parent->left->size+1;
y = y->parent;
}
return r;
}
5. Порядковые деревья
Для того чтобы при балансировке
дерево продолжало оставаться
порядковым в процедуру вращения
необходимо и достаточно добавить
строки:
y->size = x->size;
x->size = x->left->size+x->right->size +1;
42
19
93
12
α
β γ
42
11
93
19
α
β
γ
Левое
вращение
6. Порядковые деревья
Порядковые деревья позволяют осуществлять
операции доступа к элементу по данному
индексу и получения индекса по данному
элементу за время O(log(n)).
Порядковые деревья хороши для реализации
разреженных массивов.
7. B-Деревья
B-деревом называется корневое дерево в котором
Каждая вершина содержит поля хранящие
количество ключей хранящихся в ней(n);
сами ключи (с доп. инф.) в неубывающем порядке;
булевское значение (leaf), истинное когда вершина
является листом
Если x – внутренняя вершина, то она содержит
n+1 указателей на детей.
8. B-Деревья
Ключи служат границами, разделяющими
значения ключей в поддеревьях.
Все листья находятся на одной и той же
глубине (равной высоте дерева)
Число ключей в одной вершине ограничено
сверху и снизу. Обычно ограничение задают
одним числом t. Каждая вершина (кроме
листьев) содержит по меньшей мере t-1 ключ,
но не более 2t-1 ключей (полная вершина).
11. B-Деревья. Основные операции.
void BTreeSearch(x,k){
i = 1;
while ((i <= x->n)&&(k>x->key[i]))
i = i+1;
if ((i<=x->n)&&(k==x->key[i]))
return (x, i);
if (x->leaf) return null;
else return BTreeSearch(x->child[i],k);
}
12. B-Деревья. Основные операции.
// x-неполная, y-полная
void BTreeSplitChild(x, i , y){
z = NewNode(); z ->leaf = y->leaf; z->n = t-1;
for (j=1; j<t; j++) z->key[j] = y->key[j+t];
if (! y->leaf)
for(j=1; j<=t; j++) z->child[j]=y->child[j+t];
y->n = t-1;
for(j=x->n+1;j>=i+1;j--)
x->child[j+1] =x->child[j];
x->child[i] = z;
for(j=x->n; j>=i; j--) x->key[j+1] = x->key[j];
x->key[i]=y->key[t]; x->n = x->n+1;
}
21. B-Деревья. Основные операции.
При удалении вершины из B-дерева возможны
следующие случаи:
Если k находится в вершине x являющейся
листом – удаляем k из x.
23. B-Деревья. Основные операции.
Если k в внутренней вершине x, то:
Если ребенок y вершины x, предшествующий k,
содержит не менее t элементов, то находим k`,
непосредственно предшествующий k. Он
находится в листе поддерева с корнем в y. Удаляем
k` (рекурсивный вызов), заменяем ключ k на k`.
Если ребенок z, следующий за k, сдержит не менее
t элементов, поступаем аналогично.
Если y и x содержат по t-1 элементов, тогда
соединяем y, z и k. Удаляем k (рекурсивный вызов).
26. B-Деревья. Основные операции.
Если x внутренняя вершина, но k в ней нет,
найдем среди ее детей корень поддерева в
котором должен лежать искомый ключ. Если
корень содержит не менее t детей, то вершину
можно удалить рекурсивно, иначе надо
предварительно сделать один из
дополнительных шагов.
27. B-Деревья. Основные операции.
Если вершина (корень поддерева) содержит t-1
элемент, но один из ее соседей (ближних братьев)
содержит t элементов, тогда добавим в вершину
элемент вершины x разделяющий соседей, а в
вершину x поместим самый правый(левый) элемент
соседа.
Если оба соседа содержат t-1 элементов, тогда
объединим вершину с одним из соседей.