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

Графы. Модели вычислений. Структуры данных

..pdf
Скачиваний:
231
Добавлен:
01.05.2014
Размер:
2.53 Mб
Скачать

Рис. 3

Следующий по направлению к корню узел правой ветви имеет ключ 8, ранг его левого сына не меньше ранга правого сына, следовательно, условие левизны выполняется и поэтому транспонирования его левого и правого поддеревьев не требуется. Однако ранг этого узла необходимо обновить, так как его старое значение 1 не совпадает с увеличенным на 1 минимальным из рангов его потомков, то есть с числом 2. Обновив ранг, получим кучу, изображенную на рис. 4.

(2)3

 

2

10

 

 

 

 

(3)

6

 

 

 

 

1

21

1

14

 

2

12

 

 

(2)

7

 

 

 

1

23

 

1

18

 

1

24

1

37

2

8

 

 

 

 

 

 

1

33

 

 

 

1

17

1

18

 

 

 

 

 

 

 

 

 

1

26

 

 

 

Рис. 4

Теперь рассмотрим узел с ключом 7. Он имеет левого сына с ключом 37 и рангом 1 и правого сына с ключом 8 и рангом 2. Для восстановления свойства левизны в этом узле необходимо поменять местами его левое и правое поддеревья и обновить ранг. Его новым значением будет минимум

241

из рангов его потомков (это ранг нового правого сына) плюс 1, то есть 2.

Врезультате получаем дерево, изображенное на рис. 5.

(2)3

 

2

10

 

 

 

 

(3)

6

 

 

 

1

21

1

14

 

2

12

 

 

 

2

7

 

 

1

23

 

1

18

 

1

24

2

8

1

37

 

 

 

 

 

1

33

 

1

17

1

18

 

1 26

Рис. 5

Далее рассматриваем узел с ключом 6. Оба его сына имеют одинаковый ранг 2, следовательно, менять их местами не требуется. Вычислим лишь новое значение ранга: оно равно минимальному из рангов его детей (рангу правого сына) плюс 1, то есть 3. Получаем дерево, изображенное на рис. 6.

(2)3

 

2

10

 

 

 

 

 

3

6

 

 

 

1

21

1

14

 

2

12

 

 

 

2

7

 

 

1

23

 

1

18

 

1

24

2

8

1

37

 

 

 

 

 

1

33

 

1

17

1

18

 

1 26

Рис. 6

Наконец, рассматриваем узел с ключом 3, который является последним в правой ветви, полученной слиянием правых ветвей исходных куч. Его потомков (узлы с ключами 10 и 6) необходимо поменять местами для

242

восстановления свойства левизны и обновить ранг, который будет теперь равен 3. После выполнения этих операций получим левостороннюю кучу, изображенную на рис. 7. На этом выполнение операции СЛИЯНИЕ заканчивается.

 

 

 

 

 

 

 

3

3

 

 

 

 

 

 

3

6

 

 

 

 

 

10

 

 

2

12

 

 

 

2

7

1

21

1

14

1

18

1

24

 

2

8

 

37

1

23

 

 

1

33

1

17

 

 

1 18

 

 

 

 

1 26

Рис. 7

Очевидно, время выполнения операции СЛИЯНИЕ пропорционально сумме длин правых путей сливаемых куч. По свойству левосторонней кучи оно не превосходит величины log n1 + log n2 < log n + log n, где n1, n2 – количества узлов в исходных кучах, а n = n1 + n2 – количество узлов в результирующей куче. Следовательно, вычислительная сложность операции СЛИЯНИЕ равна O(log n).

Реализация операции СЛИЯНИЕ

procedure СЛИЯНИЕ(h1, h2, h); begin

if h1 = nil then {h := h2; exit}; if h2 = nil then {h := h1; exit};

if h1^.key > h2^.key then {h3 := h1; h1 := h2; h2 := h3;} h := h1; СЛИЯНИЕ(h1^. right, h2, h3); h^. right := h3; if h^.left^.rank < h^.right^.rank then

{h3:= h^.left; h^.left := h^.right; h^.right := h3}; h^.rank := min(h^.right^.rank, h^.left^.rank) + 1;

end;

Операция ВСТАВКА. Эта операция позволяет осуществить вставку в кучу h нового элемента x с ключом k. Она производится посредством об-

243

разования левосторонней кучи, содержащей единственный элемент х с ключом k, и слияния ее с кучей h. Вычислительную сложность данной операции можно оценить так же, как вычислительную сложность операции СЛИЯНИЕ, то есть величиной O (log n).

Реализация операции ВСТАВКА

procedure ВСТАВКА(x, k, h); begin

CREATE node h1: [element, key, rank, left, right, parent] = [x, k, 1, nil, nil, nil];

СЛИЯНИЕ(h, h1, h2); h := h2 end;

Операция УДАЛЕНИЕ_МИНИМУМА. Эта операция позволяет из кучи h удалить элемент хMin с минимальным ключом. Она производится посредством удаления корня кучи h (трудоемкость O (1)), а затем слияния его левой и правой подкуч (трудоемкость O (log n)). Таким образом, вычислительная сложность данной операции является величиной O (log n).

Реализация операции УДАЛЕНИЕ_МИНИНИМУМА

procedure УДАЛЕНИЕ_МИНИМУМА (h, xMin); begin

xMin := h^.element; СЛИЯНИЕ (h^.left, h^.right, h3); h := h3 end;

Операция МИНИМУМ. Эта операция позволяет взять из кучи h элемент с минимальным ключом, не удаляя его из кучи. Поскольку элемент с минимальным ключом находится в корне кучи, то требуется лишь скопировать его в нужное место. Вычислительная сложность данной операции

O (1).

Реализация операции МИНИМУМ

function МИНИМУМ (h); begin

МИНИМУМ := h^.element; end;

Операция УДАЛЕНИЕ. Эта операция позволяет удалить из кучи h элемент х, расположенный в узле, заданном позицией pos. Удаление может быть проведено в несколько этапов.

1. Если узел х является корнем кучи h, то применяется операция

244

УДАЛЕНИЕ_МИНИМУМА из кучи h. Иначе выполняются следующие действия.

2.От исходной кучи h отрывается подкуча h2 с корнем в удаляемом узле х. Оставшаяся куча, для которой сохраняем обозначение h, не обязательно является левосторонней.

3.Затем узел х удаляется из кучи h2, а его левая и правая подкучи сли-

ваются в одну кучу h2(время выполнения – O (log n), как доказано выше).

4. Куча h2делается таким же сыном узла р (р – родитель узла х), ка-

ким являлся для нее узел х (левым или правым).

5. Наконец, в куче h восстанавливается свойство левизны. Фактически свойству левизны могут не удовлетворять только узлы, находящиеся на пути от р к корню кучи h. Длина этого пути в худшем случае может линейно зависеть от n. Но на самом деле нам нужно проверить только первые не более чем log (n + 1) узлов на этом пути (потому что максимальный по длине правый путь имеет максимум log (n + 1) узлов).

Таким образом, время выполнения данной операции O (log n). Рассмотрим пример выполнения данной операции. Пусть из кучи h,

изображенной на рис. 8, необходимо удалить элемент х с ключом 9.

 

 

 

 

 

 

h:3

2

 

 

 

 

 

 

3

4

 

 

 

2

11

 

 

 

p:

 

 

 

 

 

 

 

 

2

9

 

 

2

5

1

12

1

17

 

x:

 

 

 

 

 

 

 

 

 

1

18

1

10

1

8

1

6

1

18

 

1 31

 

 

1

15

 

1 11

 

 

 

 

 

 

 

 

1

21

 

 

 

 

 

 

 

 

 

 

Рис. 8

 

 

 

 

Сначала отрывается подкуча h2 с корнем х. От h остаются куча h1 (нелевосторонняя, так как свойству левизны не удовлетворяет узел р) и левосторонняя куча h2, см. рис. 9.

245

 

 

 

 

 

 

h1:3

2

 

 

 

 

 

 

 

3

4

 

 

 

 

2

11

 

 

h2:

p:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

9

 

 

2

5

 

1

12

1

17

 

x:

 

 

 

 

 

 

 

 

 

 

1

18

1

10

1

8

1

6

 

1

18

 

1 31

 

 

1

15

 

1 11

 

 

 

 

 

 

 

 

 

1

21

 

 

 

 

 

 

Рис. 9

Затем удаляется узел х, а его левая и правая подкучи h2L и h2R сливаются в одну кучу h2при помощи вышеописанной операции СЛИЯНИЕ; см. рис. 10.

 

h2L

h2R:

 

1

h2:

1

18

 

 

10

 

1 10

1

 

 

1 31

 

18

 

 

1

31

 

 

 

 

 

 

Рис. 10

Поскольку узел х не являлся корнем кучи h, операция еще не завершена. Куча h2становится левым поддеревом узла р, так как узел х был его левым сыном, см. рис. 11.

 

 

 

(3)

 

 

h:(3)

2

 

 

 

 

 

 

 

 

 

 

 

11

 

 

 

 

p:

4

 

 

 

 

2

 

 

 

1

10

 

 

2

5

1

12

1

17

 

1

18

 

 

1

8

1

6

1

18

 

1

31

 

 

1

15

1

1 11

 

 

 

Следуем от узла

 

 

21

 

 

 

 

р к корню дерева, для каждого узла этого пути вос-

 

 

 

 

 

 

 

 

Рис. 11

 

 

246

станавливаем свойство левизны и ранг. Сначала проверяем узел р: его детей надо поменять местами, так как ранг узла с ключом 10 (он равен 1) меньше ранга узла с ключом 5 (он равен 2). После этого обновляется ранг узла р: он равен рангу правого сына плюс 1, то есть 2. Получилось дерево, изображенное на рис. 12.

 

 

 

 

 

 

h:(3)

2

 

 

 

 

 

 

2

4

 

 

 

 

2

11

 

 

2

5

 

 

 

1

1

1

12

1

17

1

8

1

6

 

1

1

 

 

1

18

 

1 15

 

1 11

 

1

31

 

 

 

 

 

 

1 21

Рис. 12

Следующий узел на пути к корню – это родитель узла р с ключом равным 2. Ранги его сыновей равны, значит менять их местами не нужно. Однако его собственный ранг возможно требует обновления, новое значение равно рангу его правого сына плюс 1, т.е. старому: 3. В результате получается дерево, изображенное на рис. 13.

 

 

 

 

 

 

h:

3

2

 

 

 

 

 

 

2

4

 

 

 

 

2

11

 

 

2

5

 

 

 

1

1

1

12

1

17

1

8

1

6

 

1

1

 

 

1

18

 

1 15

 

1 11

 

1

31

 

 

 

 

 

 

1 21

Рис. 13

Поскольку узел с ключом 2 является корнем дерева, операция

247

УДАЛЕНИЕ завершена.

Реализация операции УДАЛЕНИЕ

procedure УДАЛЕНИЕ (h, pos); begin

if pos = h then {УДАЛЕНИЕ_МИНИМУМА (h, xMin); exit};

p := pos^.parent; h2 := pos; УДАЛЕНИЕ_МИНИМУМА (h2, xMin); if p^.left = pos then p^.left := h2 else p^.right := h2;

while p nil do begin

if p^.left nil then r1:= p^.left^.rank else r1:= 0; if p^.right nil then r2:= p^.right^.rank else r2:= 0; newrank := min (r1, r2) + 1;

if r1 < r2 then tr (p^.left, p^.right);

if newrank p^.parent^.rank then p^.parent^.rank:= newrank else exit;

p:= p^.parent; end

end

Операция УМЕНЬШИТЬ_КЛЮЧ. Ключ узла x, находящегося в дереве в позиции pos, уменьшается на положительное число . Это действие может нарушить кучеобразный порядок лишь таким образом, что уменьшенный ключ узла х будет меньше ключа его родителя. Уменьшение ключа может быть проведено в несколько этапов:

1.От исходной кучи h отрывается подкуча h2 с корнем в узле х. Оставшаяся куча h не обязательно будет левосторонней.

2.Затем ключ узла х уменьшается на заданное число . Куча h2 при этом все еще остается левосторонней.

3.В куче h следующим образом восстанавливается свойство левизны. Фактически свойству левизны могут не удовлетворять только узлы, нахо-

дящиеся на пути от р (р – родитель узла х) до корня h. Длина этого пути в худшем случае линейно зависит от n. Но на самом деле нам нужно проверить только первые не более чем log (n + 1) узлов на этом пути.

Наконец, куча h сливается с h2 за время O (log n).

Таким образом, время выполнения данной операции – O (log n). Рассмотрим пример выполнения рассматриваемой операции. Пусть

в куче, изображенной на рис. 14, необходимо уменьшить ключ узла х от

248

9 до 0.

 

 

 

 

 

 

h:

3

2

 

 

 

p:

 

3

4

 

 

 

 

2

11

x:

2 9

 

 

 

 

2

5

 

1 12

1 17

1

18

1

10

 

1

8

1

6

1

18

 

1 11

1 31

 

 

 

1

15

 

 

 

1 21

Рис. 14

Делается это следующим образом. От исходной кучи h отрывается подкуча h2 с корнем в удаляемом узле х. Теперь куча h не является левосторонней, так как в узле р нарушено свойство левизны; см. рис. 15.

 

 

 

 

 

 

 

h:

(3)

2

 

 

 

 

 

p:

(3)

4

 

 

 

 

2

11

 

h2:

2

9

 

 

 

2

5

 

1 12

1 17

 

 

x:

 

 

 

 

 

1

6

 

 

 

1

18

1

10

 

1

8

1

18

 

 

1 11

1

31

 

 

 

1

15

 

 

 

1 21

Рис. 15

Ключ узла х уменьшается до 0, куча h2 при этом все еще остается левосторонней; см. рис. 16.

x: 2 0

1

18

1

10

1 31

Рис. 16

Следуем от узла р до корня дерева h, для каждого узла этого пути вос-

249

станавливаем свойство левизны и ранг. Сначала проверяем узел р: его детей надо поменять местами (а фактически – только одного-единственного правого сына сделать левым). После этого вычисляется новый ранг узла р: он равен рангу правого сына плюс 1, то есть 1 (так как правого сына нет). Получилось дерево, изображенное на рис. 17.

 

 

 

 

h: (3

2

 

 

 

 

 

 

p:

1 4

 

2

11

 

 

2

 

5

 

1

12

1

17

1

8

 

1

6

 

1

18

 

1 15

 

1

11

 

 

 

 

 

1 21

Рис. 17

Следующий узел – это родитель узла р с ключом 2. Его потомков тоже необходимо поменять местами (так как ранг левого сына меньше ранга правого). После этого ранг узла с ключом 2 вычисляется как ранг правого сына плюс 1, то есть 2. Получается куча, представленная на рис. 18:

 

 

 

h:

2 2

 

 

 

 

 

 

2

11

 

 

 

 

 

1

4

1

12

1

17

 

2

 

5

 

 

 

1

18

 

1

8

 

1

6

 

 

 

 

 

1 15

 

1

11

 

 

1 21

Рис. 18

Наконец, сливаем кучи h и h2, получая в результате левостороннюю кучу (см. рис. 19).

 

 

 

 

 

 

 

h:

2

0

 

 

 

250

 

 

 

3

2

 

 

 

 

 

1

18

 

2

11

 

 

 

2

4

 

1

31

 

1

12

 

1

17

2

5

 

1

10

 

 

 

 

1

18

 

1

8

 

1

6

 

 

 

 

 

 

 

1

15

 

1 11

 

 

 

 

 

 

 

 

 

 

1

21