Informatica 3 LEZIONE 26: Implementazioni avanzate per liste e array Modulo 1: Skip list Modulo 2: Multiliste Modulo 3: Rappresentazioni di matrici
Informatica 3 Lezione 26 - Modulo 1 Skip list
Introduzione Skip list: struttura dati probabilistica basata su liste in alternativa a BST e strutture ad albero (richiedono bilanciamento) semplice da implementare fornisce buone prestazione con alta probabilità
head Esempio 0 5 25 30 31 42 58 62 69 head 0 1 5 25 30 31 42 58 62 69 head 0 1 2 5 25 30 31 42 58 62 69
Skip list (1) Ricerca di un elemento: head si segue il puntatore di livello più alto L fino a quando si trova un valore più grande di quello cercato dal nodo dello stesso livello immediatamente precedente si prosegue la ricerca al livello L-1 e si ripete il processo Esempio: ricerca del numero 62 0 5 25 30 31 42 58 62 69 1 Caso peggiore: Θ(log n)
head Skip list (1) Ricerca di un elemento: si segue il puntatore di livello più alto L fino a quando si trova un valore più grande di quello cercato dal nodo dello stesso livello immediatamente precedente si prosegue la ricerca al livello L-1 e si ripete il processo Esempio: ricerca del numero 62 0 5 25 30 31 42 58 62 69 1 2 Caso peggiore: Θ(log n)
Skip list (2) Skip list ideale: metà dei nodi hanno un puntatore ¼ dei nodi hanno due puntatori 1/8 dei nodi hanno 3 puntatori... Distanze hanno gli stessi spazi bilanciamento Il processo per mantenere la skip list bilanciata è costoso quando si inserisce un nuovo nodo si assegna in modo random il livello al nodo con una distribuzione esponenziale 50% il nodo ha un puntatore 25% il nodo ha due puntatori
Inserimento di un nuovo nodo head head head 0 1 10 0 1 10 20 5 10 0 1 20 head head 2 5 10 20 0 2 5 10 20 30 1 2 3
Prestazioni Se molti nodi hanno molti puntatori: Θ(n) Se molti nodi hanno pochi puntatori: equivalente a una lista concatenata Θ(n) Nel caso medio tutte le operazioni: Θ(log n) in pratica la skip list è probabile che abbia prestazioni migliori di un BST un BST può avere prestazione peggiori a seconda dell ordine con cui i dati vengono inseriti nell albero la skip list non dipende dall ordine con cui i dati vengono inseriti all aumentare del numero dei nodi nella skip list, la probabilità di ottenere il caso peggiore decresce esponenzialmente
Implementazione (1) Ricerca di un valore: forward: array che contiene i puntatori dei diversi livelli della skip list template <class Key, class Elem> bool SkipList<Key, Elem>:: find(const Key& K, Elem& e) const { SkipNode<Elem> *x = head; // Dummy header node for (int i=level; i>=0; i--) while ((x->forward[i]!= NULL) && (K > x->forward[i]->value)) x = x->forward[i]; x = x->forward[0]; // Move to actual record, if it exists if ((x!= NULL) && (K == x->value)) { e = x->value; return true; } else return false; }
Implementazione (2) Determinazione del livello in base alla distribuzione esponenziale: int randomlevel(void) { int level; for (level=0; Random(2) == 0; level++); // Do nothing return level; } 0 (50%) 0 (50%) 1 (50%) -->50% 1 (50%) -->25% livello 0 livello 1
Implementazione (3) Inserimento di un nuovo nodo template <class Key, class Elem> bool SkipList<Key, Elem>:: insert(const Elem& val) { int i; SkipNode<Elem> *x = head; // Start at header node int newlevel = randomlevel(); // Select level for new node if (newlevel > level) { // New node is deepest in list AdjustHead(newLevel); // Add null pointers to header level = newlevel; } SkipNode<Elem>* update[level+1]; // Track ends of levels for(i=level; i>=0; i--) { // Search for insert position while((x->forward[i]!= NULL) && (x->forward[i]->value < val)) x = x->forward[i]; update[i] = x; // Keep track of end at level i }
Implementazione (3) Inserimento di un nuovo nodo (cont.) }... x = new SkipNode<Elem>(val, newlevel); // Create new node for (i=0; i<=newlevel; i++) { // Splice into list x->forward[i] = update[i]->forward[i]; // Where x points update[i]->forward[i] = x; // Where y points } reccount++; return true;
Informatica 3 Lezione 26 - Modulo 2 Multiliste
Introduzione Estensione della definizione di lista: multilista gli elementi di una multilista possono essere un atomo una lista: SOTTO-LISTA Notazione: (x1, (y1, (a1, a2), y3), (z1, z2), x4) sotto-lista sotto-lista sotto-lista
Lista pura Lista pura: struttura a lista il cui grafo corrisponde a un albero esiste un unico percorso per ogni nodo nessun oggetto può apparire più di una volta nella lista x1 x4 y1 y3 z1 z2 a1 a2
Lista rientrante (1) Lista rientrante: struttura a lista il cui grafo corrisponde a un DAG i nodi possono essere raggiunti dalla radice tramite più percorsi gli oggetti possono apparire più di una volta nella lista a L1 L2 L3 c d e b (((a,b)),((a,b),c),(c,d,e),(e))
Lista rientrante (2) Notazione con sottoliste etichettate: (((a,b)),((a,b),c),(c,d,e),(e)) ((L1:(a,b)),(L1,L2:c),(L2,d,L3:e),(L3)) a L1 b L2 c d L3 e
Lista ciclica: Lista rientrante (2) L4 L1 L2 b L3 c d a (L1: (L2: (a, L1)), (L2, L3: b), (L3, c, d), L4: (L4))
Implementazione tramite array Implementazione tramite array: le sottoliste possono essere viste come elementi di lunghezza variabile occorre indicare l inizio e la fine di una sottolista implementazione ad albero sequenziale l accesso all n-esimo elemento richiede una visita sequenziale della lista
Implementazione tramite liste concatenate (1) Le liste pure possono essere implementate tramite liste concatenate con un campo addizionale che indica se il nodo è un atomo o una sottolista in caso di sottolista il campo dei dati punta al primo elemento di una sottolista + x1 - - + x4 root + z1 + z2 + + y2 - a1
Implementazione tramite liste Altro approccio: concatenate (2) Tutti gli elementi della lista hanno due puntatori, eccetto gli atomi gli atomi contengono solamente i dati B C D A
Informatica 3 Lezione 26 - Modulo 3 Rappresentazioni di matrici
Introduzione Molte applicazioni devono rappresentare grandi matrici bidimensionali in cui molti elementi hanno valore 0 Esempi: matrici triangolari matrici sparse Risparmiare spazio utilizzando delle liste che contengono i valori diversi da 0
Matrice triangolare a 00 0 0 0 a 00 a 01 a 02 a 03 a 10 a 11 0 0 0 a 11 a 12 a 13 a 20 a 21 a 22 0 0 0 a 22 a 23 a 30 a 31 a 32 a 33 0 0 0 a 33 Lista di lunghezza n(n+1)/2 caso matrice triangolare inferiore: riga 1: primo elemento diverso da 0 riga 2: primi due elementi diversi da 0 la riga r è preceduta da r righe contenenti FORMULA elementi diversi da 0 aggiungendo c si raggiunge la c-esima posizione della riga matrice[r,c] = lista[(r 2 + r)/2 + c] caso matrice triangolare superiore: matrice[r,c] = lista[rn - (r 2 + r)/2 + c]
Matrice sparsa (1) Metodo 1: concatenare le coordinate r e c degli elementi con valore diverso da 0 in un unico valore e utilizzare questo valore come chiave in una tabella di hash occorre conoscere la posizione dei valori da cercare non si può trovare il primo elemento diverso da 0 in una determinata riga/colonna
Matrice sparsa (2) Metodo 2: implementazione tramite una lista ortogonale lista di puntatori a righe liste di record della matrice lista di puntatori a colonne liste di record della matrice ogni elementi diverso da 0 punta ai vicini diversi da 0 che lo precedono e gli succedono sia nella riga che nella colonna
Matrice sparsa (3) righe colonne 0 1 3 6 0 A 00 A 01 A 06 1 A 11 A 13 4 A 40 7 A 71 A 76
Matrice sparsa (4) Prestazioni in termini di spazio: se i dati, gli indici di riga e colonna e il puntatore richiedono 4 byte, una matrice nxm richiede 4nm byte se la matrice sparsa richiede 28 byte per 4 puntatori, due indici di array e un valore, una matrice nxm con X% valori diversi da 0 richiede 28nmX byte 28mnX = 4mn X = 1/7 14%