Code unificabili con alberi binomiali Laboratorio di Algoritmi
Code unificabili con alberi binomiali Laboratorio di Algoritmi 02/03 Prof. Ugo de’ Liguoro Algo. Lab - Code unificabili
ADT delle code unificabili Le code unificabili sono code di priorità che supportano le seguenti operazioni: • Make. Queue(): 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 • Decrease. Key(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. Algo. Lab - Code unificabili
Alberi binomiali • Gli alberi binomiali sono alberi finiti ordinati definiti induttivamente: • B 0 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. Algo. Lab - Code unificabili
Esempi Bo B 1 B 2 B 3 B 4 Algo. Lab - Code unificabili
Proprietà degli alberi binomiali Sia Bk l’albero binomiale di ordine k: a) ha 2 k nodi, b) ha altezza k, c) vi sono nodi al livello i, d) 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. Algo. Lab - Code unificabili
Heap binomiali Uno heap binomiale H è 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. Algo. Lab - Code unificabili
Esempio 15 H= 4 6 7 8 Algo. Lab - Code unificabili
Rappresentazione 15 0 H 4 2 root-list parent 6 7 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. Algo. Lab - 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 n 2 = b lg n -1 … b 0 Visto che e che Bi ha 2 i 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. Algo. Lab - Code unificabili
Operazioni (1) Make. Bin. Heap (): Bin. Heap ritorna uno heap binomiale vuoto. Bin. Heap. Min(Bin. Heap H): Node ritorna il puntatore al nodo con chiave minima in H: dato che gli alberi nella rootlist di H sono heap, è sufficiente scandire la root-list (lunghezza lg n + 1). Bin. Heap. Insert(Node x, Bin. Heap H): Void aggiunge un 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. Algo. Lab - Code unificabili
Operazioni (2) Bin. Heap. Extract(Bin. Heap 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. Bin. Heap. Decrease. Key(Node x, Key k, Bin. Heap 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. Algo. Lab - Code unificabili
Operazioni (3) Bin. Link(Node x, Node y): Void rende l’albero binomiale con radice in x figlio sinistro di quello con radice in y: funzione ausliaria di Bin. Heap. Union(Bin. Heap H 1, H 2): Bin. Heap costruisce l’unione di H 1 ed H 2 distruttivamente …. Algo. Lab - Code unificabili
Unione di heap binomiali Bin. Heap. Union (Bin. Heap H 1, H 2) H : = la fusione ordinata sul grado delle root-list di H 1 e H 2 x : = il puntatore al primo elemento della root-list di H while x ed il puntatore al fratello di x NIL do 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 Algo. Lab - Code unificabili
Unione (pseudocodice) Bin. Heap. Union(Bin. Heap H 1, H 2) H : = Make. Bin. Heap(); root-list[H] : = Merge(root-list[H 1], root-list[H 2]) // 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]; Bin. Link(next, x) else if prev = NIL then root-list[H] : = next else sibling[prev] : = next Bin. Link(x, next); x : = next; next : = sibling[x]; Algo. Lab - Code unificabili return H
Caso 1 prev x next a b c Bk Bl prev a x b c Bk Bl sibling[next] d next d Algo. Lab - Code unificabili
Caso 2 sibling[next] prev x next a b c d Bk Bk Bk prev a x next b c d Bk Bk Bk Algo. Lab - Code unificabili
Caso 3 prev x a b b c Bk sibling[next] next c d Bk Bl prev x next a b d c Bk+1 Bk Bk Bl Algo. Lab - Code unificabili
Caso 4 prev x a b b>c Bk sibling[next] next c d Bk Bl prev x next a c d b Bk+1 Bk Bk Bl Algo. Lab - Code unificabili
- Slides: 18