RSS    

   Реферат: VB, MS Access, VC++, Delphi, Builder C++ принципы(технология), алгоритмы программирования

           Else

               node.Balance = BALANCED

               child.Balance = BALANCED

           End If

           Set node = child

        Else

           ' Вращение влево‑вправо.

           Set grandchild = child.RightChild

           grandchild_bal = grandchild.Balance

           Set child.RightChild = grandchild.LeftChild

           Set grandchild.LeftChild = child

           Set node.LeftChild = grandchild.RightChild

           Set grandchild.RightChild = node

           If grandchild_bal = LEFT_HEAVY Then

               node.Balance = RIGHT_HEAVY

           Else

               node.Balance = BALANCED

           End If

           If grandchild_bal = RIGHT_HEAVY Then

               child.Balance = LEFT_HEAVY

           Else

               child.Balance = BALANCED

           End If

           Set node = grandchild

           grandchild.Balance = BALANCED

        End If

    End If

End Sub

Программа AVL оперирует АВЛ‑деревом. Введите текст и нажмите на кнопку Add, чтобы добавить элемент к дереву. Введите значение, и нажмите на кнопку Remove, чтобы удалить этот элемент из дерева. На рис. 7.14 показана программа AVL.

Б‑деревья

Б‑деревья (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 обращений к памяти. Вопросы, связанные с обращением к диску, позднее обсуждаются в этой главе более подробно.

Вставка элементов в Б‑дерево

Чтобы вставить новый элемент в Б‑дерево, найдем лист, в который он должен быть помещен. Если этот узел содержит менее, чем 2 * K ключей, то в этом узле остается место для добавления нового элемента. Вставим новый узел на место так, чтобы порядок элементов внутри узла не нарушился.

Если узел уже содержит 2 * K элементов, то места для нового элемента в узле уже не остается. Разобьем тогда узел на два новых узла, поместив в каждый из них K элементов в правильном порядке. Затем средний элемент переместим в родительский узел.

Например, предположим, что мы хотим поместить новый элемент Q в Б‑дерево, показанное на рис. 7.15. Этот новый элемент должен находиться во втором листе, который уже заполнен. Для разбиения этого узла, разделим элементы J, K, L, N и Q между двумя новыми узлами. Поместим элементы J и K в левый узел, а элементы N и Q — в правый. Затем переместим средний элемент, L[RV13]  в родительский узел. На рис. 7.16 показано новое дерево.

@Рис. 7.16. Б‑дерево после вставки элемента Q

=========173

Разбиение узла на два называется разбиением блока. Когда оно происходит, к родительскому узлу добавляется новый ключ и новый указатель. Если родительский узел уже заполнен, то это также может привести к его разбиению. Это, в свою очередь, потребует добавления новой записи на более высоком уровне и так далее. В наихудшем случае, вставка элемента вызовет «цепную реакцию», которая приведет к изменениям на всех вышележащих уровнях вплоть до разбиения корневого узла.

Когда происходит разбиение корневого узла, Б‑дерево становится выше. Это единственный случай, при котором его высота увеличивается. Поэтому Б‑деревья обладают необычным свойством — они всегда растут от листьев к корню.

Удаление элементов из Б‑дерева

Теоретически, удалить узел из Б‑дерева так же просто, как и вставить его. На практике, детали этого процесса достаточно сложны.

Если удаляемый узел не является листом, то его нужно заменить другим элементом, чтобы сохранить порядок элементов. Это похоже на случай удалений элемента из упорядоченного дерева или АВЛ‑дерева и его можно обрабатывать аналогично. Заменим элемент самым крайним правым элементом из левой ветви. Этот элемент всегда будет листом. После замены элемента, можно просто считать, что вместо него просто удален заменивший его лист.

Чтобы удалить элемент из листа, вначале нужно при необходимости сдвинуть все другие элементы влево, чтобы заполнить образовавшееся пространство. Помните, что каждый узел в Б‑дереве порядка K должен иметь от K до 2 * K элементов. После удаления элемента из листа, может оказаться, что он содержит всего K - 1 элементов.

В этом случае, можно попробовать взять несколько элементов из узлов на том же уровне. Затем можно распределить элементы в двух узлах так, чтобы они оба имели не меньше K элементов. На рис. 7.17 элемент удаляется из самого левого листа дерева, при этом в нем остается всего один элемент. После перераспределения элементов между узлом и правым узлом на том же уровне, оба узла имеют не меньше двух ключей. Заметьте, что средний элемент J перемещается в родительский узел.

@Рис. 7.17. Балансировка после удаления элемента

=======174

@Рис. 7.18. Слияние после удаления элемента

При попытке сбалансировать дерево таким образом, может оказаться, что соседний узел на том же уровне содержит всего K элементов. Тогда два узла вместе содержат всего 2 * K - 1 элементов, что недостаточно для заполнения двух узлов. В этом случае, все элементы из обоих узлов могут поместиться в одном узле, поэтому их можно слить. Удалим ключ, который отделяет два узла от родителя. Поместим этот элемент и 2 * K - 1 элементов из двух узлов в один общий узел. Этот процесс называется слиянием узлов (bucket merge или bucket join). На рис. 7.18 показано слияние двух узлов.

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82


Новости


Быстрый поиск

Группа вКонтакте: новости

Пока нет

Новости в Twitter и Facebook

                   

Новости

© 2010.