corso di algoritmi e strutture dati

35
Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C Esercizi su Alberi

Upload: aden

Post on 14-Jan-2016

51 views

Category:

Documents


0 download

DESCRIPTION

Corso di Algoritmi e Strutture Dati. APPUNTI SUL LINGUAGGIO C Esercizi su Alberi. Alberi. Un albero è un insieme di oggetti, chiamati nodi , su cui è definita una relazione binaria G(x,y) – che leggiamo “ x è genitore di y ” – tale che: - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Corso di Algoritmi e Strutture Dati

Corso di Algoritmi e Strutture Dati

APPUNTI SUL LINGUAGGIO C

Esercizi su Alberi

Page 2: Corso di Algoritmi e Strutture Dati

Alberi

Un albero è un insieme di oggetti, chiamati nodi, su cui è definita una relazione binaria G(x,y) – che leggiamo

“x è genitore di y” – tale che:

1. esiste un unico nodo, chiamato radice, che non ha genitori;

2. ogni nodo x diverso dalla radice ha uno ed unico genitore;

3. per ogni nodo x diverso dalla radice esiste un cammino dalla radice a x

• Se x è il genitore di y, allora y è un figlio di x.

• Un albero binario è un albero in cui ogni nodo ha al massimo due figli.

Page 3: Corso di Algoritmi e Strutture Dati

Terminologia

cammino: sequenza di nodi x1, … , xk tale che xi è il genitore di xi+1

lunghezza del cammino: k (numero degli archi)

antenato e discendente: dato un nodo x di un albero T con radice r, qualunque nodo y sul cammino (unico) da r a x è un antenato di x, mentre x è un discendente di y

fratelli: nodi che hanno lo stesso genitore

sottoalbero: insieme costituito da un nodo x e tutti i suoi discendenti; x è la radice del sottoalbero

foglia: nodo senza figli

nodo interno: nodo con uno o piu’ figli

grado: il numero di figli di un nodo x è il grado di x;

Profondita’ o Livello :• La radice ha profondita’ 0

• Se un nodo ha profondita’ k, i suoi figli hanno profondita’ k+1

Altezza dell’albero : massima profondita’ a cui si trova una foglia ovvero numero di archi nel cammino dalla radice alla foglia piu’ profonda

Page 4: Corso di Algoritmi e Strutture Dati

Alberi binari come lista concatenata

Un elemento x di una lista è un oggetto con tre campi

info[x] campo chiave

left[x] puntatore al sottoalbero (figlio) sinistro

right[x] puntatore al sottoalbero (figlio) destro

Chiamiamo tale lista T

Page 5: Corso di Algoritmi e Strutture Dati

Alberi binari come lista concatenata

head[T] puntatore al primo elemento x della lista (radice)

Albero vuoto: head[T] = NIL

head[T]

1

2 NIL2

NILNIL1 NIL4

NILNIL5

NILNIL6

Page 6: Corso di Algoritmi e Strutture Dati

// definizione della struttura nodo

typedef struct elem{

int info;

struct elem* left;

struct elem* right;

} etree;

// definizione del puntatore ai nodi dell’albero

typedef etree* ptree;

Alberi in C

Page 7: Corso di Algoritmi e Strutture Dati

void isLeaf(ptree x) {

return ((x ≠ NULL) && (x->left == NULL) &&

(x->right == NULL));

}

Verificare se un nodo è una foglia

isLeaf(x)

return x ≠ NIL and left[x] = NIL and right[x] = NIL

Page 8: Corso di Algoritmi e Strutture Dati

Esiste anche una notazione testuale detta PARENTETICA

( 1

( 2

( 4 () () )

( 5 () () ) )

( 3

( 6 () () )

( 7 () () ) )

)

Un nodo n che non ha figli è rappresentato da

( n () () )

Notazione parentetica

1

2 3

4 5 6 7

Page 9: Corso di Algoritmi e Strutture Dati

void StampaAlberoNonIndentato(ptree t) {

if (t == NULL) {

printf("()");

return;

}

printf(“( %d ", t->info);

StampaAlbero(t->left);

StampaAlbero(t->right);

printf(" )");

}

Notazione parentetica

Scriviamo in c una funzione per stampare in notazione parentetica un albero binario (senza indentare)

Page 10: Corso di Algoritmi e Strutture Dati

Notazione parentetica

Scriviamo in c una funzione per stampare in notazione parentetica un albero binario (indentando)

1. come indentare? sul livello i indentiamo con 2i spazi

2. ogni volta che incontriamo un nodo ci chiediamo

A. se è una foglia allora stampiamo il valore del nodo senza andare a capo

B. se non è una foglia allora stampiamo il valore del nodo e andiamo a capo

3. una volta stampato il valore del nodo richiamiamo la funzione in modo ricorsivo sui sottoalberi sinistro e destro

Page 11: Corso di Algoritmi e Strutture Dati

void Indenta(int livello) {

int i = 0;

for (i = 0; i < 2*livello; i++) printf(“ ”);

}

Notazione parentetica (indetata)

Page 12: Corso di Algoritmi e Strutture Dati

void StampaLivello(ptree t, int livello) {

if (t == NULL) {

Indenta(livello);

printf("() ");

return;

}

Indenta(livello);

printf("( ");

switch(isLeaf(t)) {

case 0: printf("%d\n", t->info); break;

case 1: printf("%d", t->info); break;

}

StampaLivello(t->left, livello + 1);

StampaLivello(t->right, livello + 1);

Indenta(livello);

printf(")\n");

}

Notazione parentetica (indentato)

Page 13: Corso di Algoritmi e Strutture Dati

void StampaAlberoIndentato(ptree t) {

StampaLivello(t,0);

}

Notazione parentetica (indentato)

Page 14: Corso di Algoritmi e Strutture Dati

Altezza di un albero

Massima profondità a cui si trova una foglia ovvero numero di

archi nel cammino dalla radice alla foglia più profonda

Profondita(T) {

if T = NIL then return -1

else s = Profondita(left[T])

d = Profondita(right[T])

return (Massimo(s,d)+1)

}

Massimo(a,b) {

if a > b then return a

else return b

}

Page 15: Corso di Algoritmi e Strutture Dati

Altezza di un albero

int Profondita(ptree t) {

int s, d;

if (t == NULL)

return -1;

else {

s = Profondita(t->left);

d = Profondita(t->right);

return (Massimo(s, d) + 1);

}

}

int Massimo(int a, int b) {

if (a > b) return a;

}

Page 16: Corso di Algoritmi e Strutture Dati

Presenza di un nodo in un Albero

int Presente(ptree t, int elem){

if (T == NULL) return 0;

else if (t->info == elem) return 1;

else return (Presente(t->left,elem) ||

Presente(t->right, elem));

}

Presente(T, elem){

if (T = NULL) then return false

else if info[T] = elem then return true

else return Presente(left[T],elem) or

Presente(right[T], elem)

}

Page 17: Corso di Algoritmi e Strutture Dati

Albero crescente

Un albero è crescente se:a) è vuotob) esiste un cammino radice-foglia con valori sempre crescenti

Crescente(T) {

if T = NIL then return true

if left[T] = NIL and right[T]= NIL then return true

if left[T] ≠ NIL then

if info[T] < info[left[T]] and

Crescente(left[T]) then return true

if right[T] ≠ NIL then

if info[T] < info[right[T]] and

Crescente(right[T]) then return true

return 0

}

Page 18: Corso di Algoritmi e Strutture Dati

Albero crescente

int Crescente(ptree t) {

if (t == NULL) return 1;

if (t->left == NULL && t->right == NULL) return 1;

if (t->left != NULL) {

if ((t->info < t->left->info) &&

Crescente(t->left)) return 1;

}

if (t->right != NULL) {

if ((t->info < t->right->info) &&

Crescente(t->right)) return 1;

}

return 0;

}

Page 19: Corso di Algoritmi e Strutture Dati

•Visita in preordine: Si analizza la radice, poi si visita sottoalbero sinistro e

sottoalbero destro (Es. 1, 2, 4, 5, 3, 6, 7)•Visita in postordine: Si visita prima sottoalbero sinistro, poi destro, e alla fine

la radice (Es. 4, 5, 2, 6, 7, 3, 1)•Visita Simmetrica: Prima visito il figlio sinistro, poi la radice e quindi il figlio

destro (Es. 4, 2, 5, 1, 6, 3, 7)

•Per tutte le visite: nel caso in cui l’albero sia vuoto non viene eseguita nessuna

azione

1

2 3

4 5 6 7

Visite negli alberi

Page 20: Corso di Algoritmi e Strutture Dati

1

2 3

4 5 6 7

Visita in preordine

PREORDER(T)

if T ≠ NIL then visita head[T]

PREORDER(left[T])

PREORDER(right[T])

Page 21: Corso di Algoritmi e Strutture Dati

1

2 3

4 5 6 7

Visita in preordine

void VisitaPreordine(ptree t) {

if (t == NULL) return;

printf(“%d “,t->info);

VisitaPreordine(t->left);

VisitaPreordine(t->right);

}

Page 22: Corso di Algoritmi e Strutture Dati

1

2 3

4 5 6 7

Visita in postordine

POSTORDER(T)

if T ≠ NIL then POSTORDER(left[T])

POSTORDER(right[T])

visita head[T]

Page 23: Corso di Algoritmi e Strutture Dati

1

2 3

4 5 6 7

Visita in preordine

void VisitaPostordine(ptree t) {

if (t == NULL) return;

VisitaPostordine(t->left);

VisitaPostordine(t->right);

printf(“%d “,t->info);

}

Page 24: Corso di Algoritmi e Strutture Dati

1

2 3

4 5 6 7

Visita Simmetrica

SIMMETRICA(T)

if T ≠ NIL then SIMMETRICA(left[T])

visita head[T]

SIMMETRICA(right[T])

Page 25: Corso di Algoritmi e Strutture Dati

1

2 3

4 5 6 7

Visita in preordine

void VisitaSimmetrica(ptree t) {

if (t == NULL) return;

VisitaSimmetrica(t->left);

printf(“%d “,t->info);

VisitaSimmetrica(t->right);

}

Page 26: Corso di Algoritmi e Strutture Dati

Esercizio

Data una lista L i cui nodi contengono valori interi, scrivere le seguenti procedure (pseudo-codice e implementazione in C):

– CANC-Val(L,x) che cancella nella lista L il nodo con valore x

– CONT-Val(L,x) che conta in L quanti nodi hanno valore x

– INS-Val(L,x,y) che inserisce in L un nodo con valore x dopo il nodo esistente in L con valore y (se il nodo con valore y non esiste allora sarà fatto un inserimento in coda)

Page 27: Corso di Algoritmi e Strutture Dati

Cancellazione di un nodo: dato il valore

CANC-Val(L,val)

if L = NIL then error “la lista è vuota”

else

if info(head(L)) = val then CANC-Testa(L)

else

prev <- head(L)

cur <- next(prev)

while info(cur) ≠ val and cur ≠ NIL do

prev <- cur

cur <- next(cur)

if cur ≠ NIL then next(prev) <- next(cur)

else error “non esiste l’elemento”

Page 28: Corso di Algoritmi e Strutture Dati

// funzione per cancellare in una lista un nodo con un valore dato

void cancellaVal(plist* l, int val){

plist prev,cur;

if (*l==NULL) printf(“La Lista è vuota\n");

else

if (*l->info == val) cancellaInTesta(l);

else {

prev = *l;

cur=prev->next;

while ((cur->info != val) && (cur != NULL)) {

prev = cur;

cur = cur->next;

}

if (cur == NULL) printf(“Non esiste l’elemento\n");

else {

prev->next=cur->next;

free(cur);

}

}

}

Cancellazione di un nodo: dato il valore

Page 29: Corso di Algoritmi e Strutture Dati

CONT-Val(L,val)

cont <- 0

x <- head(L)

while x ≠ NIL do

if info(x) = val then cont++

x <- next(x)

return cont

Funzione per valutare il numero di nodi con valore val

Page 30: Corso di Algoritmi e Strutture Dati

Funzione per valutare il numero di nodi con valore val

int ContaVal(plist l, int val){

int cont = 0;

while (l!=NULL) {

if (l->info == val) cont++;

l = l->next;

}

return cont;

}

Page 31: Corso di Algoritmi e Strutture Dati

Ricerca di un nodo in una lista

void funzione(plist l, valore x)

x

l

SEARCH(L,k)

if NULL(L) then return NIL

else x <- head(L)

while x ≠ NIL and info(x) ≠ k

do x <- NEXT(x)

return x

Page 32: Corso di Algoritmi e Strutture Dati

// funzione per cercare in una lista un nodo

plist search(plist l, int n){

int test = 0;

while ((l!=NULL)&&(!test))

if (l->info == n) test = 1;

else l = l->next;

return l;

}

Ricerca di un nodo in una lista

Page 33: Corso di Algoritmi e Strutture Dati

Inserimento di un nuovo nodo dopo un nodo dato

INS-Val(L,x,y)

k <- SEARCH(L,y)

if k = NIL INS-Coda(L,x)

else

info(z) <- x

next(z) <- next(k)

next(k) <- z

Page 34: Corso di Algoritmi e Strutture Dati

// funzione per inserire un nodo con valore x

void inserisciVal(plist *l, int x, int y) {

plist k = Search(*l,y);

if (k == NULL) inserisciInCoda(l,x);

else {

plist z = (plist)malloc(sizeof(elist));

z->info = x;

z->next = k->next;

k->next = z;

}

}

Inserimento di un nuovo nodo dopo un nodo dato

Page 35: Corso di Algoritmi e Strutture Dati

Corso di Algoritmi e strutture Dati

APPUNTI SUL LINGUAGGIO C

Esercizi su alberi

FINE