Laboratorio di Algoritmi e Strutture Dati II Semestre 2005/2006 Alberi di Ricerca Marco Antoniotti Operazione di rimozione in un BSTs • • Abbiamo visto le operazioni search e insert per BSTs Ora vediamo una semplice, ma problematica, operazione di rimozione (delete) di un nodo, ovvero di una coppia <key, value> • BST delete – – – Caso 0 (niente sottoalberi): si rimuove il nodo senza problemi Caso 1 (un sottoalbero): si rimuove il nodo e lo si sostituisce con la radice dell’unico sottoalbero Caso 2 (due sottoalberi): si trova il nodo successore del nodo da rimuovere d, lo so scambia con d e si procede come nei casi precedenti Problemi: strategia macchinosa e non simmetrica L’abero risultante non è simmetrico anche se random e la profondità può crescere fino a √N II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 1/15 1 Rimozione “pigra” (lazy delete) • • Per facilitare le operazioni di rimozione possiamo anche esser “pigri” (“lazy”) Invece di rimuovere effettivamente un nodo lo si marca come “rimosso” – Le operazioni di inserimento e ricerca devono trattare questi nodi in modo particolare • Costi: O(lg(N’)) per inserimento, ricerca e rimozione, dove N’ è il numero totale di inserimenti II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 2/15 Dizionari a confronto Caso peggiore • • Caso medio Implementazione Search Insert Delete Search Insert Delete Array ordinato lg(N) N N lg(N) N/2 N/2 Lista non ordinata N N N N/2 N N Hash Table N 1 N 1* 1* 1* BST N N N lg(N) lg(N) lg(N) BST: solite assunzioni (casualità e N = numero totale inserimenti per lazy delete) Domanda: possiamo migliorare le prestazioni dei BST rimuovendo la dipendenza dall’input? II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 3/15 2 Rotazioni • Rotazioni: operazioni fondamentali per riarrangiare i nodi negli alberi – Mantengono le invarianti dei BSTs – Sono locali: cambiano solo tre puntatori II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 4/15 Rotazione Destra e Rotazione Sinistra // Nota: senza controlli su puntatori nulli. // L’uso di sentinelle facilita le operazioni. BinaryNode* rotLeft(BinaryNode* h) { BinaryNode* x = h->getRight(); h->setRight(x->getLeft()); x->setParent(h->getParent()); x->setLeft(h); return x; } BinaryNode* rotRight(BinaryNode* h) { BinaryNode* x = h->getLeft(); h->setLeft(x->getRight()); x->setParent(h->getParent()); x->setRight(h); return x; } II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 5/15 3 Inserimento alla Radice • Root insert: si inserisce unnuovo nodo e lo si rende la radice – – • Si inserisce usando la stessa struttura di insert Si ruota il nodo fino alla radice Perchè far ciò? – – Le ricerce degli elementi appena inseriti sono più veloci Queste operazioni sono la base per algoritmi su BST più sofisticati BinaryNode* rootInsert(BinaryNode* h, Key k, Value v) { if (h == 0) return new BinaryNode(k, v); if (k < h->getKey()) { h->setLeft(rootInsert(h->getLeft(), k, v)); return rotRight(h); } else { h->setRight(rootInsert(h->getRight(), k, v)); return rotLeft(h); } } II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 6/15 Inserimento alla radice: esempio Esempio: A S E R C H I N G X M P L II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 7/15 4 Alberi “Randomizzati” con Inserimento alla Radice • • Si ricordi: se le chiavi sono inserite in modo casuale, allora il BST è essenzialemente bilanciato (con alta probabilità) Idea: quando si inserisce un nuovo nodo, lo si inserisca alla radice con probabilità 1(N+1) e si ripeta ricorsivamente BinaryNode* insertNodeR(BinaryNode* h, Key k, Value v) { if (h == 0) return new BinaryNode(k, v); if ((rand() / (float) RAND_MAX) * (h->count() + 1) < 1) return rootInsert(h, k, v); // si inserisce usando piu` o meno la normale insertNode // … h->incrCount(); return h; } • Risultato: la forma dell’albero è simile a quella ottenuta assumendo inserimenti casuali – Ma ora non abbiamo più questa dipendenza II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 8/15 Laboratorio Algoritmi - Marco Antoniotti 9/15 Esempio • Inseriamo le chiavi in ordine crescente II Semestre 2005/2006 5 “Randomized” BST • Proprietà: assomiglia sempre ad un albero random Θ(lg(N)) caso medio Implementazione: dimensione del (sotto)albero contenuta nel nodo Probabilità di sbilanciamento molto bassa II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 10/15 “Randomized” BST: altre operazioni • Operazione join: congiungere due BSTs A (dimensione M) e B (dimensione N) assumendo che tutte le chiavi in A siano minori delle chiavi in B – Si usa A come radice con probabilità M/(M+N) e si congiunge (join) ricorsivamente il sottoalbero destro di A con B – Si usa B come radice con probabilità N/(M+N) e si congiunge (join) ricorsivamente il sottoalbero sinistro di B con A • Operazione delete: si rimuove il nodo e si congiungono (join) i due sottoalberi • Teorema: l’albero risultante è ancora casuale (random) II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 11/15 6 Dizionari a confronto Caso peggiore • • Caso medio Implementazione Search Insert Delete Search Insert Delete Array ordinato lg(N) N N lg(N) N/2 N/2 Lista non ordinata N N N N/2 N N Hash Table N 1 N 1* 1* 1* “Randomized” BST lg(N) lg(N) lg(N) lg(N) lg(N) lg(N) “Randomized BST: prestazioni logaritmiche “garantite” (ammesso di avere a disposizione un buon generatore di numeri casuali) Domanda: possiamo dare delle garanzie di prestazioni deterministiche? II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 12/15 BSTs: operazioni ulteriori • Ordinamento: dopo l’inserimento basta produrre una lista “inordine” del contenuto • Ricerca tra limiti (range search): trovare tuttle le chiavi comprese tra k1 e k2 • Trovare il k-esimo (più grande o più piccolo) elemento – – – – Generalizzazione di una coda con priorità Caso speciale: massimo e minimo Si usa la dimensione del sottoalbero Tempo proporzionale alla profondità II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 13/15 7 Dizionari a confronto Caso asintotico Implementazione Search Insert Delete Find kth Sort Join Ceil Array ordinato lg(N) N N lg(N) N N lg(N) Lista non ordinata N N N N N lg(N) N N Hash Table 1* 1* 1* N N lg(N) N N BST N N N N N N N “Randomized” BST lg(N) lg(N) lg(N) lg(N) N lg(N) lg(N) II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 14/15 Sommario • Operazioni di delete di un nodo da un BST – Diretta – “lazy” • Problema: albero può diventare sbilanciato • Operazioni di rotazione di un nodo • Operazioni di “inserimento alla radice” • Alberi esplicitamente randomizzati (con operazione di inserimento alla radice) – Rimozione della dipendenza dall’input II Semestre 2005/2006 Laboratorio Algoritmi - Marco Antoniotti 15/15 8