180 likes | 307 Views
Code unificabili con alberi binomiali. Laboratorio di Algoritmi 02/03 Prof. Ugo de’ Liguoro. ADT delle code unificabili. Le code unificabili sono code di priorità che supportano le seguenti operazioni: MakeQueue (): crea una coda vuota; Enqueue ( x , Q ): aggiunge un elemento x alla coda
E N D
Code unificabili con alberi binomiali Laboratorio di Algoritmi 02/03 Prof. Ugo de’ Liguoro AlgoLab - Code unificabili
ADT delle code unificabili • Le code unificabili sono code di priorità che supportano le seguenti operazioni: • MakeQueue(): crea una coda vuota; • Enqueue(x,Q): aggiunge un elemento x alla coda • Minimum(Q): ritorna l’elemento di chiave minima in Q (il minimo) • Dequeue (Q): elimina da Q il minimo • DecreaseKey(x,k,Q): ridefinisce la chiave di x in Q con il valore k, posto che essa fosse k • Union(Q,Q): costruisce una coda unificando distruttivamente Q e Q. AlgoLab - Code unificabili
Alberi binomiali • Gli alberi binomiali sono alberi finiti ordinati definiti induttivamente: • B0 ha un solo nodo; • Bk+1 è formato da due alberi Bk di cui la radice del primo sia il figlio più a sinistra della radice del secondo: Bk+1 Bk Bk Gli alberi binomiali si chiamano cosi perché, tra le loro craratteristiche, vi è che il livello i dell’albero Bk ha esattamente nodi. AlgoLab - Code unificabili
Esempi Bo B1 B2 B3 B4 AlgoLab - Code unificabili
Proprietà degli alberi binomiali Sia Bk l’albero binomiale di ordine k: • ha 2k nodi, • ha altezza k, • vi sono nodi al livello i, • la radice ha k figli i quali, se numerati da sinistra a destra con k 1, k 2, …, 0 allora il figlio i-esimo è un albero Bi. Dim. Vedi Cormen, cap. 20. AlgoLab - Code unificabili
Heap binomiali • Uno heap binomialeH è un insieme di alberi binomiali tale che: • gli alberi siano degli heap minimi, ossia la chiave di un nodo è di quella del padre (se esiste); • per ogni k in H vi è al più un albero di grado k. • Il grado di un nodo è il numero dei suoi figli; il grado (o arietà) di un albero è il massimo dei gradi dei suoi nodi. Si osservi che il grado della radice di Bk è k. AlgoLab - Code unificabili
Esempio 15 4 H = 6 7 8 AlgoLab - Code unificabili
Rappresentazione 15 4 0 2 H root-list 6 7 parent 1 0 key degree 8 0 child sibling Si osservi come la root-list sia ordinata in modo crescente rispetto al grado, mentre la lista dei fratelli di un nodo non radice sia decrescente sul grado. AlgoLab - Code unificabili
Osservazioni Se H ha n nodi, allora H consta di al più lg n + 1 alberi binomiali: • lg n + 1 è il numero dei bit nella rappresentazione binaria di n n2 = b lg n b lg n -1 … b0 • Visto che e che Bi ha 2i nodi, l’albero Bi occorre in H se e solo se bi = 1: quindi di questi alberi ve ne sono al massimo lg n + 1. AlgoLab - Code unificabili
Operazioni (1) MakeBinHeap (): BinHeap ritorna uno heap binomiale vuoto. BinHeapMin(BinHeap H): Node ritorna il puntatore al nodo con chiave minima in H: dato che gli alberi nella root-list di H sono heap, è sufficiente scandire la root-list (lunghezza lg n + 1). BinHeapInsert(Node x, BinHeap H): Void aggiungeun nodo precedentemente allocato x (di cui sia dunque definito il valore della chiave) allo heap binomiale H: crea uno heap vuoto, vi inserisce l’albero il cui unico nodo è x, quindi unisce H con il nuovo heap binomiale. AlgoLab - Code unificabili
Operazioni (2) BinHeapExtract(BinHeap H): Node ritorna il puntatore al nodo x con chiave minima in H, eliminandolo dalla coda: eliminato x dalla root-list di H, prima di deallocarlo forma uno heap binomiale H la cui root-list è la lista dei figli di x in ordine inverso (quindi con grado crescente); quindi unisce H ed H. BinHeapDecreaseKey(Node x, Key k, BinHeap H): Void ridefinisce la chiave del nodo x con il valore k (che si ipotizza sia minore del valore originario della chiave di x), ristrutturando la relativa componente di H: consiste nello scambio tra x e il padre di x ogni volta che quest’ultimo abbia chiave > k. AlgoLab - Code unificabili
Operazioni (3) BinLink(Node x, Node y): Void rende l’albero binomiale con radice in x figlio sinistro di quello con radice in y: funzione ausliaria di BinHeapUnion. BinHeapUnion(BinHeap H1,H2): BinHeap costruisce l’unione di H1 ed H2 distruttivamente …. AlgoLab - Code unificabili
Unione di heap binomiali BinHeapUnion (BinHeap H1, H2) H := la fusione ordinata sul grado delle root-list di H1 e H2 x := il puntatore al primo elemento della root-list di H while x ed il puntatore al fratello di x NILdo if x ed il fratello hanno diverso grado or x è la prima di tre radici con lo stesso grado then x := il puntatore al successivo nella root-list else // x è la prima di due radici con lo stesso grado fondi l’albero con radice in x con quello successivo, facendo diventare radice del nuovo albero quella con la chiave minore x := il puntatore alla radice del nuovo albero return H AlgoLab - Code unificabili
Unione (pseudocodice) BinHeapUnion(BinHeap H1, H2) H := MakeBinHeap(); root-list[H] := Merge(root-list[H1],root-list[H2]) // ordinando in modo non decrescente sul grado if root-list[H] = NIL then return H else prev := NIL; x := root-list[H]; next := sibling[x]; while next NIL do if degree[x] degree[next] or (sibling[next] NIL and degree[sibling[next]] = degree[x]) then prev := x; x := next else if key[x] key[next] then sibling[x] := sibling[next]; BinLink(next,x) else if prev = NIL then root-list[H] := next else sibling[prev] := next BinLink(x,next); x := next; next := sibling[x]; return H AlgoLab - Code unificabili
Caso 1 prev x next a b c d Bk Bl sibling[next] prev x next a b c d Bk Bl AlgoLab - Code unificabili
Caso 2 prev x next a b c d Bk Bk Bk sibling[next] prev x next a b c d Bk Bk Bk AlgoLab - Code unificabili
Caso 3 prev x next a b d c Bk+1 Bk Bl Bk sibling[next] prev x next b c a b c d Bk Bk Bl AlgoLab - Code unificabili
Caso 4 prev x next a c d b Bk+1 Bk Bl Bk sibling[next] prev x next b > c a b c d Bk Bk Bl AlgoLab - Code unificabili