Tutorato di Algoritmi e Strutture Dati [CT0371] Lezione 8: 3 Dicembre 2013 Tutor: Alberto Carraro Disclaimer: Queste note non sono state sottoposte al consueto controllo riservato alle pubblicazioni ufficiali. Esse dunque possono essere distribuite al di fuori di queste lezioni solo con il permesso del docente. In questa lezione rivediamo gli argomenti visti a lezione durante la settimana: • Alberi BST - definizione • funzione Search(Node x, Elem k), calcolo della sua complessità e controllo della correttezza. • funzione Minimum(Node x), calcolo della sua complessità • funzioni Predecessore(Node x) e Successore(Node x), calcolo della complessità • funzione Insert(Tree t, Node z) • funzione delete(Tree t, Node z) e della funzione ausiliaria Transplant(Tree t, Node u, Node v) che trapianta il sottoalbero radicato in v nella radice u. Ricordiamo che un BST A è un albero binario (memorizzato con una struttura a nodi linkati) tale che per ogni nodo x in A, ogni nodo y nel sottoalbero sinistro di x ed ogni nodo z nel sottoalbero destro di x abbiamo che y.key ≤ x.key ≤ z.key. Esercizio 1 (Appello del 03-02-09) Discutere la complessità asintotica dell’algoritmo di ricerca di una chiave in un albero BST con n nodi. Svolgimento: TREE-SEARCH(x, k) if (x == NIL OR k == x.key) return x if (k < x.key) return TREE-SEARCH(x.left, k) else return TREE-SEARCH(x.right, k) Il tempo di calcolo è O(h), dove h è l’altezza dell’albero. Attenzione che la complessità in generale non è O(log n), visto che il caso peggiore è un albero a forma di linea che non contiene la chiave k. Alla peggio dunque il tempo di esecuzione è O(n), mentre se il BST è completo la complessità scende a O(log n). Esercizio 2 (Appello del 05-02-10) Un nodo di un albero binario è detto centrale se il numero di foglie del sottoalbero di cui è radice è pari alla somma delle chiavi dei nodi appartenenti al percorso dalla radice al nodo stesso. a. Scrivere una funzione efficiente in C che restituisca il numero di nodi centrali. 8-1 8-2 Lezione 8: 3 Dicembre 2013 b. Discutere la complessità della soluzione trovata. c. Se vogliamo modificare la funzione in modo che restituisca l’insieme dei nodi centrali che tipo di struttura dati si può utilizzare per rappresentare l’insieme? La complessità dell’algoritmo deve rimanere la stessa che nel caso (a). Si deve utilizzare il seguente tipo per la rappresentazione di un albero binario: typedef struct Node{ int key; struct node * left; struct node * right; } * Node; Svolgimento: int centrali(Node * x, int * count, int keysum){ int leaf_number = 0; if (x != NULL){ if (x-> left == NULL && x->right == NULL){ if (keysum == 1) (*count)++; return 1; } else{ int left_leaf_number = centrali(x->left, count, keysum+(x->key)); int right_leaf_number = centrali(x->right, count, keysum+(x->key)); leaf_number = left_leaf_number+right_leaf_number; if (keysum == leaf_number) (*count)++; } } return leaf_number; Se root è un puntatore alla radice dell’albero e count è una variabile intera, questa funzione va invocata cosı̀: int leaves = centrali(root, &count, 0); Alla fine ritroviamo in leaves il numero di foglie dell’albero e in count il numero di nodi centrali. La complessità della nostra soluzione è Θ(n) dove n è il numero di nodi dell’albero. References [1] C. Demetrescu, I. Finocchi, G.F. Italiano, Algoritmi e strutture dati 2/ed. McGraw-Hill, 2008. [2] T.H. Cormen, C.E. Leiserson, R.L. Rivest, C. Stein, Introduzione agli algoritmi e strutture dati 3/ed, McGraw-Hill, 2010.