430 likes | 806 Views
Algorytmy i struktury danych. Koszt zamortyzowany Drzewa dwumianowe Kopce dwumianowe Kopce Fibonacciego. Koszt zamortyzowany. Ś redni koszt poj. operacji w kontekście całej sekwencji
E N D
Algorytmy i struktury danych Koszt zamortyzowany Drzewa dwumianowe Kopce dwumianowe Kopce Fibonacciego
Koszt zamortyzowany Średni koszt poj. operacji w kontekście całej sekwencji Koszt średni – wymaga rozkładu prawdopodobienstwa danych we. i probabilistycznej analizy czasu wykonania alg. Koszt zamortyzowany – rozważa sie np. wymagane sekwencje operacji i na tej postawie okresla koszt jednostkowej operacji Przyklad: ciąg operacji na stosie.
Kopce – koszt operacji Kopce binarne* / dwumianowe* / fibonacciego** • wstawianie elementów (log n) / O(log n) / (1) • znajdowanie minimalnego węzła (1) / O(log n) / (1) • usuwanie minimalnego węzła (log n) / (log n) / O(log n) • czas łączenia – (n) / O(log n) / (1) • zmniejszanie klucza elementu (log n) / (log n) / (1) • usuwanie węzła (log n) / (log n) / O(log n) * Koszt pesymistyczny **Koszt zamortyzowany
Drzewa dwumianowe Definicja: Bk-1 B0 Bk-1 Bk B0 B1 B2 B3 B4
Drzewa dwumianowe – właściwości Bk . . . . B0 B1 B2 Bk-2 Bk-1 Bk • Liczba węzłów = 2k • Wysokość = k • Na głębokości i znajduje się węzłów • Stopień korzenia jest k i jest największy w całym drzewie k i
Kopiec dwumianowy 6 1 8 14 29 12 25 11 17 38 18 27 • Każde drzewo w H jest uporządkowane kopcowo (klucz w węźle jest nie mniejszy niż klucz ojca) • Dla każdego d0 istnieje w H co najwyżej jedno drzewo którego korzeń ma stopień = d • Reprezentacja poszczególnych drzew w notacji na lewo syn na prawo brat H 10
Kopce dwumianowe - deklaracja class BNNODE : key = None degree = 0child = None sibling = Noneparent = None data = None root = None
Kopce dwumianowe - Min def MinBNHeap(heap):min = heapwhile heap != None:if heap.key < min.key:min = heapheap = heap.siblingreturn min
Kopce dwumianowe - TreeLink 11 12 12 11 19 18 18 19 z’ y z + = Bz Bz By By z y z’ 1 4 1 + = 25 27 4 25 27
Kopce dwumianowe - TreeLink def LinkBNTree(newSon, newParent)newSon.parent = newParent newSon.sibling = newParent.childnewParent.child = newSonnewParent.degree = newParent.degree +1
Kopce dwumianowe - Union Scal listy drzew dla łączonych kopców (zachowując uporzadkowanie wg. stopni Tak długo jak na liscie są drzewa o jednakowych stopniach scalaj drzewa
Kopce dwumianowe - Union 3 10 17 28 28 11 45 17 48 3 10 48 11 45 17 3 17 41 27 24 50 25 17 25 41 51 17 50 24 25 51 27 25 27 12 15 18 6 33 8 29 9 30 22 31 35 12 15 18 6 33 8 29 9 30 22 31 35 12 3 12 18 27 18
Kopce dwumianowe - Union 11 17 28 45 48 45 48 10 28 11 17 10 17 41 24 25 25 24 41 17 51 50 50 51 12 3 15 6 18 27 33 8 29 9 30 22 31 35 12 3 6 18 27 15 8 29 9 33 30 22 31 35
Union - przypadki X NextX a a b c b d Bk Bl Bm 1 przejdz w prawo tj. X = NextX, NextX = NextX.sibling l > k 2 l = k = m przejdz w prawo tj. X = NextX, NextX = NextX.sibling 3 l = k < m, a<=b TreeLink(NextX, X) 4 TreeLink(X, NextX) l = k < m, a>b
Union - implementacja def MergeBNHeap(h1, h2)ret = Nonecur = Nonewhile h1!=None and h2!=None: if h1.degree<=h2.degree: next,h1 = h1,h1.sibling else: next,h2 = h2,h2.sibling if ret == None: ret, cur = next, next else: cur.sibling,cur = next,nextif h1==None: h1,h2=h2,h1if ret==None: return h1else cur.sibling = h1return ret def UnionBNHeap(y, z):ret = MergeBNHeap(y, z)if ret == None: return NoneprevX=NoneX=retnextX= ret.sibling while nextX != None:# przypadki 1..4 return ret
Union – implementacja cd. if X.degree != nextX.degree or\ #przypadek 1 (nextX.sibling!=Noneand\ nextX.degree == nextX.sibling.degree): #przypadek 2prevX,X,nextX = X,nextX,nextX.sibling elif X.key <= nextX.key: #przypadek 3X.sibling = nextX.siblingnextX.sibling = NoneLinkBNTree(nextX, X)nextX=X.sibling else:# przypadek 4if prevX==None: ret = nextX else: prevX.sibling = nextXLinkBNTree(X, nextX)x.sibling = NoneX,nextX = nextX,nextX.sibling
Kopce dwumianowe - Insert def InsertBNHeap(heap, key, data) node= PBNNODE()#node.sibling = node.parent = node.child = None#node.degree = 0 node.key = key node.data = data return UnionBNHeap(heap, node)
Kopce - ExtractMin 13 13 40 10 19 42 42 10 19 40 37 51 24 50 17 17 51 24 37 50 18 7 8 29 21 30 11 32 32 18 21 29 8 + 32 30 11 32
ExtractMin - Implementacja Dla minimalnego węzła MIN usun drzewo zaczynające się od MIN z kopca H Utwórz nowy kopiec H’ z synów MIN Wykonaj Union na H i H’ def ExtractMinBNHeap(heap):ret = MinBNHeap(heap)usun_ret_z_listy_korzeni_w_heaph1 = odwroc_kolejnosc_synow_ret_i_zwroc_ich_listeheap = UnionBNHeap(heap, h1)ret.sibling= Noneret.child = Nonereturn heap,ret
Kopce – Decrease Key 10 3 10 23 3 48 48 23 23 48 3 10 15 15 24 15 15 24 15 24 15 50 50 50 18 4 8 21 40 30 22 31 7 45 32 18 4 55 8 21 40 7 22 31 30 32 55 18 4 7 21 40 8 22 31 30 32 55
Decrease Key - Implementacja Zmien klucz dla węzła w while w jest mniejszy od ojca:zamień oba węzły def DecKeyBNHeap(node, newKey):if newKey > node.key: ERRORnode.key = newKey whilenode.parent!=Noneand node.key<node.parent.key:node.key, node.parent.key = node.parent.key, node.keynode.data,node.parent.data=node.parent.data,node.data node = node.parent
Remove Node - Implementacja def RemoveBNHeap(heap, node):tmp = node.keyDecKeyBNHeap(node, MINKEYVALUE)heap,node = ExtractMinBNHeap(heap)node.key = tmpreturn heap,node MINKEYVALUE musi bycMNIEJSZYod wszystkich kluczy lub można poszukać minimalnego klucza
Kopce Fibbonacciego Zbliżone do kopców dwumianowych, mają jednak luźniejszą strukturę. • zamortyzowany czas wstawiania – O(1) • zamortyzowany czas min– O(1) • zamortyzowany czas łączenia – O(1) • zamortyzowany czas zmniejszenia klucza – O(1) • zamortyzowany czas usuwania i ExtractMin O(log n) • Koszt zamortyzowany – w odróżnieniu od analizy średniego przypadku nie wymaga rozważań probabilistycznych.
Kopiec Fibonacciego • Każde drzewo w H jest jest uporządkowane kopcowo (klucz w węźle jest nie mniejszy niż klucz ojca) a początek drzewa wskazuje na minimalny węzeł • Drzewa nie są uporządkowane między sobą • Reprezentacja poszczególnych drzew: listy cykliczne dla poziomów drzewa i wskaźnik do jednego z synów; usuwanie wierzchołka i sklejanie list = O(1) • Zaznaczenie wybranych wierzchołków (węzły które utraciły syna od chwili kiedy ostatnio zostały synem) • Maksymalny stopien D(n) = logf n; f=(1+5) /2 HF 11 3 24 6 17 26 40 31 18 52 38 30 41 35
Sklejanie list cyklicznych prev prev prev prev prev prev prev data data data data data data data next next next next next next next def JoincycleLists(L1, L2):if L1==None: return L2 if L2==None: return L1if L1.next==L1 : L1.prev = L2.prev #L1 miala 1 el. else: L1.next.prev = L2.prev if L2.prev==L2 : L2.next = L1.next #L2 miala 1 el. else: L2.prev.next = L1.next L1.next,L2.prev = L2, L1 L2 L1 L2'
Kopce Fibonacciego - deklaracja class HFNODE: key=None degree=0 child=None left=None right=Noneparent=None marked=Falsedata=NoneHF=Nonesize=0 HF 11 3 24 6 17 26 40 31 18 52 38 30 41 35
Kopce Fibonicciego - Insert 3 3 17 17 38 38 18 18 52 52 31 31 41 30 41 30 • Dodawany wezeł staje się oddzielnym drzewem i nie jest zaznaczony HF + 11 24 21 6 26 46 35 HF 11 24 6 21 26 46 35
Kopce Fibonicciego - Insert def InsertFibHeap(heap, key, size, data):node= PHFNODE()#node.parent = node.child = NULL#node.marked = falsenode.left = nodenode.right = nodenode.key = keynode.data = dataheap = JoinCycleLists( heap, node )size = size+1if heap.key<node.key: return heap,size else: return node,size
Kopce Fibonicciego - Union def UnionFibHeap (heap1, heap2,size1, size2):heap = JoinCycleLists( heap1, heap1) size = size1 + size2 if heap1.key < heap2.key: return heap1,size else return heap2,size
Kopce Fibonicciego - ExtractMin przenieś synów Min do H dopóki korzeń każdego drzewa w FH nie ma innego stopnia znajdź dwa korzenie x, y o tym samym stopniu, takie że x->key <= y->key usuń y z listy korzeni H dołącz y do x zwieksz stopien x Consolidate: FibHeapLink:
Kopce Fibonicciego - ExtractMin 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 3 17 17 17 17 17 17 38 18 38 18 38 18 18 38 38 18 18 38 52 31 31 31 31 31 31 41 30 30 41 41 30 30 41 30 41 41 30 HF 11 24 6 21 11 24 6 21 52 26 46 26 46 35 35 w,x x 11 24 6 24 6 21 21 52 52 w 26 46 26 46 11 35 35 x 6 52 21 x 6 24 w 21 52 24 11 26 46 w 11 26 46 35 35
Kopce Fibonicciego - ExtractMin 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 11 11 11 18 38 38 38 31 31 31 30 41 41 41 w,x w,x 6 52 6 18 21 24 24 21 30 17 17 52 26 46 26 46 35 35 HF w,x 6 18 24 21 30 17 52 26 46 35
Kopce Fibonicciego - ExtractMin def ExtractMinFibHeap(heap, size):min = heapif min != None: heap = RemoveFromCycleList(heap, min) for c in all_children_of_min c.parent = None heap = JoinCycleList(heap, min.child) size = size-1 if heap != heap.left: heap = Consolidate(heap) return heap, size, min
Kopce Fibonicciego - Consolidate def Consolidate(heap, size):A = Array(D(size),None)for x in all_nodes_in_heap: d = x.degree; while A[d] != None: y = A[d] if x.key > y.key: x,y = y,x heap = FibHeapLink(heap, x, y) A[d] = None d = d+1 A[d] = x heap = None # merge nodes from A into heap for i in range(0, D(size)): if A[i] != NULL ): A[i].left = A[i] A[i].right = A[i] heap = JoinCycleList(heap, A[i]) if heap.key > A[i].key: heap = A[i]
Kopce Fibonicciego - Consolidate def FibHeapLink(heap, x, y):heap = RemoveNodeFromCycleList( heap, y ) x.child = JoinCycleList( x.child, y) x.degree = x.degree+1 y.mark = Falsereturn heap
Kopiec Fibonacciego Jeżeli nie wykonujemy operacji: • ExtractMin • Delete to drzewa w kopcu pozostają nieuporządkowanymi drzewami wielomianowymi Przy wykonywaniu ExtractMin i Delete maksymalny stopień węzła wynosi D(n) = D(n) = logf n; f=(1+5) /2 i taki jest koszt zamortyzowany obu operacji
Kopce Fibonicciego - DecKey 11 11 11 11 11 11 38 38 38 38 38 38 30 31 31 31 31 31 41 41 41 41 41 41 HF HF 15 6 18 24 21 30 17 26 15 52 35 HF HF 15 6 18 15 4 6 18 24 21 39 17 21 24 30 17 26 52 26 52 4 35 HF 6 18 HF 24 21 30 17 6 18 15 4 26 18 15 4 26 24 6 52 26 46 21 21 24 30 17 30 17 35 52 52
Kopce Fibonicciego - ExtractMin parent = x.parent if parent != None and x.key < parent.key :przenieś_x_do_korzenia_kopca x.marked = False if parent.marked: powtorz_cala_procedure_rekurencyjnie dla parent else: parent.marked = True
Kopce Fibonicciego - DecKey def DecKeyFibHeap(heap, x, newK):if x.key < newK : ERRORx->key = newK p = x.parentif p != None and x.key < p.key: heap = CutFibHeap(heap, x, p) heap = CascadingCutFibHeap (heap,p)if x.key < heap.key: heap = x;
Kopce Fibonicciego – Cut def CutFibHeap(heap, x, p):RemoveFromCycleList(p.son, x)p.degree = p.degree –1x.left, x.right = x, xheap = JoinCycleList(heap, x)x.parent = Nonex.mark = False def CascadingCutFibHeap(heap, p):z = p.parentif z != None: if not z.marked: z.marked = True else: CutFibHeap(heap, p, z ) CascadingCutFibHeap(heap, z)
Kopce Fibonicciego – DelKey • Zmniejsz klucz do najmniejszej możliwej wartosci • Wykonaj ExtractMin def DelKeyFibHeap(heap, x, size):heap = DecKeyFibHeap(heap, x, MINKEYVALUE)heap,size,x = ExtractMinFibHeap(heap, size)return heap,size MINKEYVALUE musi bycMNIEJSZYod wszystkich kluczy lub można poszukać minimalnego klucza