Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Методические указания / Нелинейные структуры данных

.pdf
Скачиваний:
2
Добавлен:
29.06.2024
Размер:
277 Кб
Скачать
☆

храняются. Если же при включении в поддерево L высота этого поддерева увеличивается на единицу, то возможны следующие три случая:

•если hl = hr, то после добавления вершины поддеревья L и R станут разной высоты, но свойство сбалансированности сохранится;

•если hl < hr, то после добавления новой вершины L и R станут равной высоты, т.е. сбалансированность общего дерева улучшится;

•если hl > hr, то после включения ключа критерий сбалансированности нарушится и потребуется перестройка дерева.

Существует лишь два случая, каждый из которых требует индивидуального подхода к балансировке (рис. 6, а, б). Результаты балансировок показаны на рис. 6, в, г. (переходы от несбалансированных схем деревьев к соответствующим сбалансированным показаны стрелками). Примеры балансировок после включения узлов приведены на рис. 7. При исключении вершин из АВЛдерева также возможна его балансировка. Удаление терминальных вершин и вершин с одним потомком тривиально, вершину с двумя потомками заменяют на самую правую (левую) вершину его левого (правого) поддерева. Балансировка, возможно, потребуется, если уменьшилась высота дерева [3].

1.4. В-деревья

Механизм классических B-деревьев был предложен в 1972 г. Байером и Мак-Крейтом с целью организации эффективного внешнего поиска. B-дерево порядка m представляет собой сильноветвящееся дерево, удовлетворяющее следующим условиям [5]:

1.Каждый узел имеет не более m потомков.

2.Каждый узел, за исключением корня и листьев, имеет не менее m/2 потом-

ков (через m/2 обозначено округление вправо, т.е. взятие наименьшего целого числа, которое не меньше m/2).

3. Корень, если он не является листом, имеет минимум двух потомков.

11

В

А

А

В

а

С

в

В

 

 

 

 

А

А

С

 

 

 

В

 

 

б

 

 

 

 

 

г

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 6. Несбалансированность после включения – а, б; итоги балансировки – в, г

 

 

38

 

 

30

 

 

 

30

40

 

22

 

 

 

 

 

 

 

 

38

 

 

22

36

 

 

 

 

 

 

 

 

20

25

36

 

40

20

25

 

 

 

 

 

 

 

 

 

38

 

 

 

 

 

 

 

 

 

 

36

 

 

 

30

40

 

 

 

 

 

 

 

 

 

30

 

38

 

22

 

36

 

 

 

 

 

 

 

 

22

35

37

40

 

 

35

37

 

 

 

 

Рис. 7. Примеры балансировки АВЛ-деревьев после включения узлов

12

4.Все листья находятся на одном уровне и не содержат информации.

5.Нелистовой узел с k потомками содержит k-1 ключей.

На рис. 8 показан пример B-дерева порядка 5. Узлы В-дерева называются страницами. Они содержат ключи и ссылки на другие страницы. Ключи в каждом узле расположены в порядке возрастания слева направо с использованием естественного обобщения концепции симметричного порядка, количество листьев на единицу больше количества ключей. Так как листья являются «пустыми», ссылки из предшествующих листьям страниц можно сделать ни на что не указывающими.

40

20

30

50

60

5 7 10 15

22 25 27 29

32 33 35 37

42 44 46 48

52 54 56 59

62 64 70 75

Рис. 8. B-дерево порядка 5

Поиск в B-дереве прямолинеен. Рассмотрим поиск заданного ключа k. В основную память считывается корневая страница B-дерева. Предположим, что она содержит ключи k1, k2, ..., kn и ссылки на страницы p0, p1, ..., pn. В ней последовательно (или с помощью какого-либо другого метода поиска в основной памяти) ищется ключ k. Если он обнаруживается, поиск завершен. Иначе возможны три ситуации:

1.Если в считанной странице обнаруживается пара ключей ki и ki+1 такая, что ki <k <ki+1, поиск продолжается на странице, на которую указывает pi.

2.Если обнаруживается, что k > kn, поиск продолжается на странице, на которую указывает pn.

3.Если обнаруживается, что k < k1, поиск продолжается на странице, на которую указывает p0.

13

Для внутренних страниц поиск продолжается аналогичным образом, пока либо не будет найден ключ k, либо не будет достигнута листовая страница (обнаружена необходимость перехода по ссылке, которая ни на что не указывает). Если достигнута листовая страница, ключ k в B-дереве отсутствует.

Чтобы вставить новый ключ k в B-дерево порядка m, в котором все листья расположены на уровне l, необходимо вставить новый ключ в подходящее место на уровне l-1. Можно осуществить поиск ключа k описанным выше способом и дойти до нужной страницы А, предшествующей листовой. Далее возможны два случая. Если страница А содержит менее m ссылок на потомков, ключ k помещается на свое место, определяемое порядком сортировки ключей в странице. Если же данная страница уже заполнена, то необходимо разбить страницу А на две страницы. При этом создается новая страница C. Ключи из страницы A и ключ k поровну распределяются между A и C, а средний ключ вместе со ссылкой на страницу C переносится в непосредственно родительскую для А страницу B (рис. 9). Такое деление может повлечь деление страницы B и т.д. до корня, который также может быть разделен. В последнем случае будет создан новый корень (высота дерева увеличится на единицу), в который переместится средний ключ из совокупности ключей предыдущей корневой страницы и ключа k. При исключении различают два случая – удаление ключа из страницы, непосредственно предшествующей листовой, и удаление ключа из внутренней страницы. В первом случае удаляемый ключ убирается из списка ключей. Во втором случае для сохранения корректной структуры B-дерева удаляемый ключ необходимо заменить минимальным (максимальным) ключом страницы, предшествующей листовой, достигнутой при переходе от страницы с удаляемым ключом вначале по самой правой (левой), а затем по всем самым левым (правым) ссылкам. В любом из указанных случаев может возникнуть ситуация, в которой одна из страниц после удаления будут содержать меньшее, чем требуется, количество ключей. Поэтому если в некоторой странице А ко-

личество ключей оказалось меньшим, чем m/2 -1, необходимо осуществить

14

процедуру перераспределения ключей или слияния. Для этого берется одна из соседних (в частности, с максимальным количеством ключей) листовых страниц – страница В (у страниц А и В имеется общая страница-предок); если на странице B имеется не менее m/2 ключей, возможно перераспределение. При этом ключи, содержащиеся в страницах А и В, а также средний ключ страницыпредка поровну распределяются между ними, и новый средний ключ заменяет тот, который был заимствован у страницы-предка.

а б

Рис. 9. Пример включения в B-дерево (листья не показаны): а – попытка вставить ключ 23 в заполненную страницу; б – выполнение включения ключа 23

Если количество ключей на странице В равно минимально возможному –

m/2 -1, следует выполнить процедуру слияния страниц А и В. При этом к ключам страниц А и В добавляется средний ключ из страницы-предка (из страни- цы-предка он изымается), эти ключи формируют содержимое страницы, полученной слиянием страниц А и В. Поскольку в странице-предке число ключей уменьшилось на единицу, может оказаться, что число элементов в ней стало меньше m/2 -1, тогда на этом уровне выполняется процедура перераспределения, а возможно, и слияния. Так может продолжаться до внутренних страниц, находящихся непосредственно под корнем B-дерева. При необходимости слияния страниц, общим предком которых является корень, содержащий единственный ключ, высота дерева уменьшится на единицу. Пример удаления ключа из В-дерева порядка 5 со слиянием показан на рис. 10.

15

Рис. 10. Пример удаления ключа 29 из B-дерева

1.5.Алгоритмы на графах

Сформальной точки зрения граф представляет собой упорядоченную пару G = (V, E) множеств, первое из которых состоит из вершин или узлов графа,

авторое – из его ребер. Ребро связывает между собой две примыкающие друг к другу (соседние) вершины и часто обозначается этой парой вершин. Графы бывают ориентированными (орграфами) и неориентированными. В орграфе ребро представляет собой упорядоченную пару вершин – начало и конец, в неориентированном графе – неупорядоченную пару вершин, его концов. Путь в графе или орграфе – последовательность ребер, по которым можно поочередно проходить. Во взвешенном графе каждому ребру приписано число, называемое весом ребра. Граф называется связным, если всякую пару узлов можно соединить по крайней мере одним путем. Цикл – это путь, который начинается и заканчивается в одной и той же вершине. Более подробно с терминологией можно ознакомиться в [4]. При работе с графами часто приходится выполнять некоторое действие по одному разу с каждой вершиной графа. Подобный обход может быть выполнен двумя способами – в глубину или по уровням. В обоих случаях одна из вершин графа выбирается в качестве отправной точки.

Обход в глубину

При обходе в глубину посещается первый узел, а затем происходит перемещение вдоль ребер графа до тех пор, пока не встретится тупик. Узел неориентированного графа является тупиком, если все примыкающие к нему узлы уже были посещены. В орграфе тупиком также называется узел, из которого

16

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

Обход по уровням

При обходе по уровням после посещения первого узла посещаются все соседние с ним вершины. При втором проходе посещаются все вершины, находящиеся на расстоянии двух ребер от начальной. При каждом новом проходе обходятся все вершины, расстояние от которых до начальной на единицу больше предыдущего. Для предупреждения повторного посещения необходимо либо вести список посещенных вершин, либо хранить информацию о посещении в соответствующей структуре данных узла.

Алгоритмы поиска минимального остовного дерева

Минимальным остовным деревом (МОД) связного взвешенного графа называется его связный подграф, состоящий из всех вершин исходного графа и некоторых его ребер, причем сумма весов ребер является минимально возможной. Такое дерево может понадобиться, например, для организации компьютерной сети.

Дейкстра и Прим предложили так называемый «жадный» алгоритм построения МОД. «Жадные» алгоритмы действуют, используя в каждый момент часть исходных данных и принимая лучшее решение на основе этой части. В рассматриваемом случае на каждом шаге имеется множество ребер, которые могут быть присоединены к уже построенной части остовного дерева, из них выбирается ребро с наименьшим весом. Вершины графа разбиваются на три класса: вершины, вошедшие в уже построенную часть дерева, вершины, окаймляющие построенную часть, и еще не рассмотренные вершины. Алгоритм начинает работу с произвольной вершины графа, которая включается в остовное дерево. Все вершины, соединенные (соседние) с данной, заносятся в кайму. За-

17

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

Другой алгоритм построения МОД предложил Крускал. Алгоритм начинает работу с пустого дерева. К нему добавляются ребра в порядке возрастания их весов до тех пор, пока не будет получен набор ребер, объединяющий все вершины графа. В процессе выполнения необходимо не допускать добавление ребер, приводящих к появлению цикла в создаваемом дереве. Если ребра закончатся до того, как все вершины будут соединены между собой, это означает, что граф был несвязным, и полученный результат представляет собой объединение МОД всех его компонент связности [4].

2.Задания к лабораторному практикуму

2.1.Лабораторная работа №1

«Программирование алгоритмов реализации и обработки древовидных

структур неспециального вида»

Цель работы

Получение навыков реализации и использования деревьев неспециального вида, анализ эффективности работы с ними.

Задание

Осуществить программную реализацию одного из деревьев, выбранных из табл. 1 приложения, в соответствии с заданным номером варианта. Программой должны выполняться функции (п. 1.1) по работе с деревом. Следует предусмотреть удобный пользовательский интерфейс, позволяющий создавать дерево и осуществлять его обработку. По результатам работы программы необходимо оценить зависимость среднего времени операции произвольного досту-

18

па к элементу от размера дерева (количества уровней и количества узлов). В программе следует предусмотреть генерацию дерева заданной степени, предоставляя пользователю возможность указывать среднюю степень узла и дисперсию. Например, если для некоторого дерева среднее равно шести, а дисперсия – двум, то в среднем по дереву у каждого узла будет примерно от 4 до 8 потомков (необходимо учитывать также максимальную степень дерева). Для генерации количества узлов следует использовать закон распределения, указанный в табл. 1 для выбранного варианта задания. К сгенерированному дереву должны быть применимы все реализованные функции. Помимо перечисленных в п. 1.1, обязательными являются функции просмотра дерева, просмотра последовательностей обхода дерева. Можно реализовать иные дополнительные функции.

Контрольные вопросы

1.Деревья – основные понятия, способы обхода.

2.Функции, выполняемые над деревьями.

3.Представление деревьев с помощью массива.

4.Представление деревьев посредством списков дочерних узлов.

5.Представление деревьев с помощью указателей.

2.2. Лабораторная работа №2

«Программирование алгоритмов реализации и обработки древовидных

структур специального вида»

Цель работы

Получение навыков создания и обработки АВЛ- и B-деревьев, анализ эффективности работы с ними.

Задание

Осуществить программную реализацию АВЛили B-дерева заданного порядка, с указанным типом ключа, выбрав из табл. 2 приложения соответствующие номеру варианта исходные параметры.

19

Программа должна предоставлять удобный пользовательский интерфейс, позволяющий создавать дерево (формировать пользователем или генерировать автоматически) и осуществлять предусмотренные виды его обработки.

Набор функций, необходимых для работы с деревом, должен включать, как минимум: генерацию дерева, поиск с включением узла, удаление узла, удаление дерева. С помощью статистического анализа необходимо определить формы зависимостей скоростей работы алгоритмов построения, поиска и включения, удаления и (или) перестраивания от размера дерева и построить соответствующие графики.

Контрольные вопросы

1.АВЛ-деревья.

2.Поиск с включением в АВЛ-дерево, исключение из АВЛ-дерева.

4.В-деревья.

5.Включение в В-дерево, исключение из В-дерева.

6.Статистический анализ скоростей выполнения операций вставки/удаления в АВЛ-, В-деревья.

2.3. Лабораторная работа №3

«Программирование алгоритмов реализации и обработки графов»

Цель работы

Получение навыков реализации алгоритмов обхода графов и построения минимальных остовных деревьев.

Задание

Осуществить программную реализацию алгоритма обработки графа, выбрав из табл. 3 приложения алгоритм и начальные параметры, в соответствии с заданным номером варианта. В программе необходимо предусмотреть удобный пользовательский интерфейс, позволяющий создавать граф (пользователем или

20