Algorytmy i Struktury Danych, 5. ¢wiczenia
2007-11-03
1 Plan zaj¦¢
• przypomnie¢ programowanie dynamiczne, np. mno»enie ªa«cucha macie- rzy, odlegªo±¢ edycyjna,
• dkopce i implementacja Dijkstry,
• reprezentacja drzew w tablicy o rozmiarze liniowym (sprawdzenie czy kra- w¦d¹ jest w drzewie w czasie stalym),
• kolorowanie grafow planarnych 6 kolorami,
• reprezentacja grafow planarnych w tablicy liniowej (sprawdzenie czy kra- w¦d¹ jest w drzewie w czasie stalym),
• kopce lewicowe wraz z DecreaseKey.
2 Drzewa lewicowe
Drzewo lewicowe to drzewo binarne, speªniaj¡ce:
•
• warunek kopca: key(x) ≥ key(parent(x)),
• oraz dist(left(x)) ≤ dist(right(x)), gdzie dist(x) jest odlegªo±ci¡ do naj- bli»szego potomka o mniej ni» 2 synach (przyjmujemy, »e dist(null) = −1).
Przydatna wªasno±¢: Je±li v jest korzeniem drzewa lewicowego, to zawiera ono co najmniej 2dist(a)w¦zªów. Czyli je±li drzewo zawiera n w¦zªów, to dist(root) = O(log n).
Podstawow¡ operacj¡ jest zª¡czanie dwóch drzew:
Merge(a, b)
1: if a=null then
2: return b;
3: else if b=null then
4: return a;
5: end if
6: if key(b) < key(a) then
7: swap(a, b)
8: end if
1
9: left(a)=merge(left(a), b)
10: if dist(right(a)) > dist(left(a)) then
11: swap(right(a), left(a))
12: end if
13: if right(a)=null then
14: dist(a)=0
15: else
16: dist(a)=1+dist(right(a))
17: end if
18: return a
atwo pokaza¢, »e zªo»ono±¢ operacji merge wynosi O(dist(a) + dist(b)), czyli O(log n).
Operacje insert i extractMin mo»na zaimplementowa¢ u»ywaj¡c operacji merge.
Insert(r, x)
1: p=MakeTree(x)
2: r=Merge(r, p)
ExtracMin(r)
1: min=r.value
2: r=Merge(r.left, r.right)
3: return min
Operacje IncreaseKey/DecreaseKey mo»emy zaimplementowa¢ w nast¦puj¡cy sposób (zakªadamy »e drzewo lewicowe to T , zmieniany w¦zeª to v, a nowa warto±¢ to x):
• usuwamy wskazany w¦zeª v z drzewa T (musimy zadba¢ by wszystkie warunki drzewa lewicowego byªy nadal zachowane)
• tworzymy jednoelementowe drzewo lewicowe T0 z warto±ci¡ x,
• scalamy T i T0.
Usuwanie w¦zªa z drzewa mo»emy wykona¢ w nast¦puj¡cy sposób:
RemoveNode(v)
1: zast¡p v przez Merge(v.left, v.right)
2: p=v.parent
3: while p 6= nil do
4: if dist(p.left) < dist(p.right) then
5: swap(p.left, p.right)
6: end if
7: if dist(p) = dist(p.right) + 1 then
8: break
9: else
10: dist(p) = dist(p.right) + 1; p = p.parent
11: end if
12: end while
Analiza pojedynczego kroku p¦tli while:
• vnale»y do poddrzewa p.left:
je±li wykonano operacj¦ swap, to drzewo musi mie¢ co najmniej 2k w¦zªów (gdzie k to odlegªo±¢ pomi¦dzy v i p)
2
wpp. algorytm ko«czy dziaªanie,
• v nale»y do poddrzewa p.right, jednak zauwa»my, »e liczba kroków tego typu nie mo»e przekroczy¢ O(log n)
3 d-kopce
dkopiec do drzewo zupeªne o stopniu d z porz¡dkiem kopcowym (min w korze- niu). Nale»y pokaza¢, »e poszczególne operacje wykonuje si¦ w czasie:
• Min O(1)
• DeleteMin O(d · logd(n))
• DecreaseKey O(logd(n))
Koszt implementacji algorytmu Dijkstry, przy u»yciu dkopców: O(nd · logd(n) + m · logd(n)).
Zanalizowa¢ jak nale»y dobra¢ d w zale»no±ci od m i n (je±li za d we¹miemy max(2, dm/ne)to dostajemy O(log m/nm log n)).
4 Reprezentacja drzew w tablicy o rozmiarze li- niowym
Utrzymujemy tablic¦ parent[v], w której zapisujemy identykator ojca w¦zªa x (lub -1 dla korzenia). Testowanie, czy istnieje kraw¦d¹ (x, y): return (pa- rent[x]==y || parent[y]==x).
5 Grafy planarne
n − m + f = 2
(n liczba wierzchoªków, m liczba kraw¦dzi, f liczba ±cia«) m ≤ 3v − 6
1 2
Xdeg(vi) ≤ 3n − 6
Xdeg(vi) ≤ 6n − 12
czyli w grae planarnym istnieje wierzchoªek o stopniu co najwy»ej 5.
3