CORSO DI PROGRAMMAZIONE  II
This presentation is the property of its rightful owner.
Sponsored Links
1 / 30

CORSO DI PROGRAMMAZIONE II Lezione 19 Operazioni sugli alberi prof. E. Burattini a.a. 2009-2010 PowerPoint PPT Presentation


  • 76 Views
  • Uploaded on
  • Presentation posted in: General

CORSO DI PROGRAMMAZIONE II Lezione 19 Operazioni sugli alberi prof. E. Burattini a.a. 2009-2010. CANCELLAZIONE DI UN NODO DI UN ALBERO.

Download Presentation

CORSO DI PROGRAMMAZIONE II Lezione 19 Operazioni sugli alberi prof. E. Burattini a.a. 2009-2010

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

CORSO DI PROGRAMMAZIONE II

Lezione 19

Operazioni sugli alberi

prof. E. Burattini

a.a. 2009-2010


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

CANCELLAZIONE DI UN NODO DI UN ALBERO

La cancellazione di un nodo di un albero presuppone che una volta avvenuta venga mantenuta l’integrità dell’albero e che nel caso si tratti di un BST si salvaguardata anche la relazione tra i vari nodi.


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Cancellazione in un albero non ordinato

Nel caso degli alberi non ordinati è necessario preoccuparsi solo di mantenere l’integrità dell’albero non essendoci relazioni d’ordine tra i vari nodi.

E’ pertanto sufficiente scorrere l’albero per trovare il nodo da cancellare, conoscendo ad esempio la chiave. Se viene trovato, è sufficiente ricercare una foglia dell’albero, non importa quale, sostituire la chiave della foglia a quella da cancellare e quindi eliminare la foglia.

Nel lucido seguente è mostrato un esempio.


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Nel caso dell’albero di figura si vuole canecllare il nodo con chiave 30. Poichè la chiave esiste è allora sufficiente cercare una foglia, ad esempio quella con chiave 28, sostituire questa chiave a quella da cancellare e eliminare la foglia.

10

10

3

3

28

30

44

44

35

35

50

50

3

28

3

8

8

35

35

38

38


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Cancellazione in un albero ordinato BST

  • Nel caso degli alberi ordinati è necessario preoccuparsi non solo di mantenere l’integrità dell’albero ma anche la relazione d’ordine esistente tra i vari nodi.

  • Vanno distinti tra casi:

  • Il nodo da cancellare è una foglia

  • Il nodo da cancellare ha un solo figlio

  • Il nodo da cancellare ha sia un sotto albero destro che un sotto albero sinistro.


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Nella figura seguente si mostrano i primi due casi che sono di semplice soluzione.

Infatti se il nodo è una foglia è sufficiente eliminarla ponendo a NULL il puntatore del parent (padre) che la riguardava. Si vedano gli esempi (a) e (b).

Nel caso in cui il nodo da cancellare ha un solo sottoalbero, è allora sufficiente legare la radice del sotto albero a cui punta il nodo da cancellare, con il parent che punta al nodo. In questa maniera, ovviamente si preserva l’ordine. Si vedano gli esempi (c) e (d).


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Old

New

Parent

Old

New

Parent

Parent

Old

Old

ELIMINAZIONE DI UN NODO SU UN BST

(b)

(a)

(c)

(d)


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Nel caso in cui il nodo da cancellare abbia sia il sotto albero di sinistra che quello di destra allora si procede come segue:

si sostituisce alla chiave del nodo da cancellare o la chiave del nodo di valore maggiore del suo sottoalbero di sinistra o quelladivalore minoredel suo sotto albero di destra.

Se questo nodo ha a sua volta un sottoalbero di destra o uno di sinistra ci si comporta nei suoi confronti come se fosse un nodo da cancellare e quindi si esegue la stessa procedura sopra descritta.


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Nodo da cancellare

35

30

40

5

40

5

8

3

80

35

3

8

80

35

38

38

Nell’esempio di figura si sostituisce alla chiave 30 del nodo individuato, la chiave del nodo 35 che è la più piccola del suo sottoalbero destro.


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Parent

Candidate

QQQ

RRR

left

right

Analizziamo il problema della riorganizzazione dell’albero una volta eliminato un nodo.

Caso a- il nodo (QQQ) da eliminare ha il sotto albero sinistro vuoto. Nell’esempio si usa la stessa nomenclatura che verrà utilizzata in seguito nel codice.

Il puntatore che da Parent prima puntava a Candidate ora acquista il valore del puntatore a RRR ottenuto in questo caso da Candidate->right


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Toni

Sergio

Toni

Sergio

Maria

Parent

Giulio

Riccardo

Dora

Guido

Candidate

Anna

Roberto

Maria

Giulio

QQQ

RRR

Dora

Guido

Riccardo

left

right

Anna

Roberto

Analizziamo il problema della riorganizzazione dell’albero una volta eliminato un nodo.

Caso a- il nodo (QQQ) da eliminare ha il sotto albero sinistro vuoto.

Eliminare

Riccardo

Caso b- il nodo da eliminare ha il sotto albero destro vuoto.

La procedura è analoga alla precedente.


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Pseudo Codice

if (Candidate->left==NULL)

LegaPadre(Candidate, Candidate ->right, Padre, Tree)

else

if (Candidate->right==NULL))

LegaPadre(Candidate, Candidate ->left, Padre, Tree)

else

continua a riorganizzare l’albero

Parent

Candidate

QQQ

RRR

left

right

void LegaPadre(Tnodo OldChild, Tnodo NewChild, Tnodo Padre, Tnodo &Tree)

{riorganizza l’albero BST dopo l’eliminazione di un nodo}


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

void LegaPadre(Tnodo OldChild, Tnodo NewChild, Tnodo Padre, Tnodo &Tree)

//collega il nodo genitore con il sottoalbero connesso al nodo da cancellare

{

if (Padre==NULL)//{sostituiamo la root}

Tree= NewChild;

else

if (OldChild ==Padre->left)

Padre->left=NewChild; //{sostituiamo al genitore il figlio sinistro}

else

Padre->right=NewChild; //{sostituiamo al genitore il figlio destro}

}

Old

Parent

New

Old

New


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Old

Parent

New

Old

New

35

30

40

5

40

5

8

3

80

3

8

35

80

35

38

38

Riassunto dei tipi di cancellazione

void DelTNode(int KeyValue, Tnodo &Tree, bool &Done) {elimina il nodo con chiave KeyValue ricostruendo la struttura BST. Se il Nodo non esiste Done risulta False}


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Fornisce il puntatore della Key da eliminare e quello del suo genitore. Se Candidato=NULL significa che la Key non c’è.

Cerca(Tree, Key, Candidato, Parent)

DammiChiave(Candidato, CandsKey)

Fornisce la chiave CandsKey di Candidato

Se la chiave trovata e quella di partenza non corrispondono CandsKey=NULL allora esci

if CandsKey<> Key

Pesudo codice di DelTNode(Key, Tree, Done)

else

Se il sottoalbero destro è vuoto collega il genitore di Candidato con la radice del sotto albero sinistro. Se Parent=NULL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero sinistro.

Se il sottoalbero sinistro è vuoto collega il genitore di Candidato con la radice del sotto albero destro. Se Parent=NULL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero destro.

Se nessuno dei due sotto alberi è vuoto allora chiama NuovoCandidato


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

void DelTNode(int KeyValue, Tnodo &Tree, bool &Done)

{ Tnodo Candidato; // puntatore al nodo candidato per la cancellatura

Tnodo Padre; // puntatore al genitore del nodo candidato}

int CandsKey;

Done=true;

Cerca( Tree, KeyValue, Candidato, Padre);

DammiChiave(Candidato, CandsKey);

if (CandsKey!=KeyValue)

Done=false;

else

if (Candidato->left==NULL)

LegaPadre(Candidato, Candidato->right, Padre, Tree);

else

if (Candidato->right==NULL) {

LegaPadre(Candidato, Candidato->left, Padre, Tree);

}

else

NuovoCandidato(KeyValue, Candidato, Tree);

KillTNode(Candidato);

}

Se il sottoalbero sinistro è vuoto collega il genitore di candidato con la radice del sotto albero destro. Se Padre =NULL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero destro.

Non c’è niente da cancellare

Se il sottoalbero destro è vuoto collega il genitore di candidato con la radice del sotto albero sinistro. Se Padre=NULL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero sinistro.

Se nessuno dei due sotto alberi è vuoto allora chiama NuovoCandidato


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Sostituisci il nodo da cancellare con Candidate

Riprendi la chiave del nodo spostato

Cerca il più piccolo nodo del sottoalbero destro del nodo spostato a partire dalla sua primitiva posizione

Collega il sottoalbero destro con il padre del nodo spostato

Se il nodo da cancellare è la root allora collega il sottoalbero destro con la root

void NuovoCandidato(int KeyValue, Tnodo &Candidato, Tnodo &Tree)

{Tnodo Dummy; //variabile ausiliare per la chiamata a Cerca

Tnodo Padre; Tnodo OldCandidato;

int CandsKey;

OldCandidato= Candidato;

Cerca(OldCandidate->right, KeyValue, Dummy, Candidato)

OldCandidato->key= Candidato->key;

DammiChiave(Candidato, CandsKey);

Cerca(OldCandidate->right, CandsKey, Dummy, Padre)

if (Padre==NULL)

LegaPadre(Candidato, Candidato->right, OldCandidato, Tree);

else

LegaPadre(Candidato, Candidato->right, Padre, Tree);

}

Ricerca OldCandidate a partire dal suo nodo destro con la conseguenza che trova il più piccolo di questo sottoalbero (Candidato) (Dummy vale NULL)


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Tnode==NULL

NodesKey <> KeyValue

if (NodesKey > KeyValue)

TNode  radice del sottoalbero sinistro

else

TNode  radice del sottoalbero destro

Cerca

Cerca(Tree, KeyValue, TNode, Padre)

Obiettivo: cercare un cammino verso un determinato nodo dell’albero.

Se il nodo non esiste ritorna NULL. Se esiste ritorna il puntatore al nodo individuato e quello di suo padre.

Il padre dell’ultimo nodo esaminato

durante la ricerca di KeyValue

Pseudo Codice

Padre  NULL {la root non ha genitori}

TNode  Tree {la radice è il primo nodo esaminato}

DammiChiave(TNode, NodesKey){estrai la chiave del nodo in esame}

while ci sono altri nodi da esaminare AND non si è ancora trovato il nodo {

Padre  TNode

Tnode  il sottoalbero legato al KeyValue

DammiChiave(TNode, NodesKey){estrai la chiave del nodo in esame}


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

void Cerca(Tnodo Tree, int KeyValue, Tnodo &Node, Tnodo &Padre)

{

int NodesKey;

Padre=NULL;

Node=Tree;

DammiChiave(Node, NodesKey) ;

while ((Node!=NULL) && (NodesKey!=KeyValue))

{

Padre=Node;

if (NodesKey>KeyValue)

Node=Node->left;

else

Node=Node->right;

DammiChiave(Node, NodesKey);

}

};

Ricordarsi che DammiChiave nel caso trovi NULL ritorna una chiave nulla.

void DammiChiave(Tnodo TNode, int &TheKey)

{ //ritorna il key field del nodo puntato da Tnode, se Tnode è

// NULL allora ritorna il valore di -100

if (TNode != NULL )

TheKey= TNode ->key;

else

TheKey= -100;

}


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

NuovoCandidato

(K,N,T)

Cerco il più piccolo a destra. Parto a destra di K cerco K e così ottengo il più piccolo, U

Cerca

(N->right, K, D, U)

DammiChiave

(Uk,U)

A partire dal sotto albero destro di N, cerco Uk per avere suo padre P

Cerca

(N->right, Uk, D, P)

P=NULL

PNULL

LegaPadre

(U,U->right,N,T)

LegaPadre

(U,U->left,N,T)

RICAPITOLANDO

Cancella il

nodo K

dell’albero T

DelTNode

(K,T,d)

Cerca in T il nodo K. Il suo puntatore è N e P è suo padre

Cerca

(T,K,N,P)

Verifica che a N corrisponde la chiave K

DammiChiave

(K,N)

La chiave non cè: ESCI

N->left=NULL

N->right=NULL

LegaPadre

(N,N->right,P,T)

LegaPadre

(N,N->left,P,T)

Collega il padre P con N->right e cancella N

Collega il padre P con N->left e cancella N

NuovoCandidato

(K,N,T)


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Fornisce il puntatore della Key da eliminare e quello del suo genitore. Se Candidato=NULL significa che la Key non c’è.

Cerca(Tree, Key, Candidato, Parent)

DammiChiave(Candidato, CandsKey)

Fornisce la chiave CandsKey di Candidato

Se la chiave trovata e quella di partenza non corrispondono CandsKey=NULL allora esci

if CandsKey<> Key

RICAPITOLANDO

Pesudo codice di DeleteTNode(Key, Tree, Done)

else

Se il sottoalbero destro è vuoto collega il genitore di Candidato con la radice del sotto albero sinistro. Se Parent=NULL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero sinistro.

Se il sottoalbero sinistro è vuoto collega il genitore di Candidato con la radice del sotto albero destro. Se Parent=NULL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero destro.

Se nessuno dei due sotto alberi è vuoto allora chiama NuovoCandidato


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

a

KeyValue=b

Node=P(b)

Padre =P(a)

b

OldChild

NewChild

Padre

OldChild

NewChild

RICAPITOLANDO

Cerca(Tnodo Tree, int KeyValue, Tnodo &Node, Tnodo &Padre)

fornisce il puntatore Candidato del node che ha chiave Key e il puntatore Padre come padre

LegaPadre(Tnodo OldChild, Tnodo NewChild, Tnodo Padre, Tnodo &Tree)

collega NewChild con Parent eliminando OldChild,

se Padre =NULL, cioè Old=Tree è la radice allora mette NewChildal posto di OldChilde quindi di Tree


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

RICAPITOLANDO

NuovoCandidato(int KeyValue, Tnodo &Candidato, Tnodo &Tree)

Cerca nel sottoalbero destro di OldCandidato il nodo con chiave minima. Questa chiave va a sostituire quella del nodo OldCandidato. Inoltre se il nodo con chiave minima ha sotto alberi allora opera come precedentemente visto.

OldCandidato

35

40

5

8

3

80

35

Candidato

38

void NuovoCandidato(int KeyValue, Tnodo &Candidato, Tnodo &Tree)

{ Tnodo Dummy; //variabile ausiliare per la chiamata a Cerca

Tnodo Padre; Tnodo OldCandidato;

int CandsKey;

OldCandidato= Candidato;

Cerca(OldCandidate->right, KeyValue, Dummy, Candidato)

OldCandidato->key= Candidato->key;

DammiChiave(Candidato, CandsKey);

Cerca(OldCandidate->right, CandsKey, Dummy, Padre)

if (Padre==NULL)

LegaPadre(Candidato, Candidato->right, OldCandidato, Tree);

else

LegaPadre(Candidato, Candidato->right, Padre, Tree);

}


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

90

50

95

93

98

30

34

17

40

100

P30

13

NULL P34

15

36

47

34

34

P34 P36

35

P35

Cancellare il nodo 30

DelTNode(KeyValue, Tree, Done)

Cerca(Tree, KeyValue, Candidate, Parent)

DammiChiave(Candidate, CandsKey);

if CandsKey<> KeyValue Done=FALSE

else

if (Candidate->left==NULL)

LegaPadre(Candidate, Candidate-> Right, Parent, Tree)

else

if (Candidate->right==NULL))

LegaPadre(Candidate, Candidate-> Left, Parent, Tree)

else

NuovoCandidato(KeyValue, Candidate, Tree);

KillTNode(Candidate);

NuovoCandidato(KeyValue, Candidate, Tree)

30

OldCandidate = Candidate

Cerca( OldCandidate->right), KeyValue, Dummy, Candidate)

OldCandidate->Key = Candidate^.Key;

CandsKey = Candidate->Key;

Cerca(OldCandidate->right, CandsKey, Dummy, Parent);

if Parent = NULL THEN

LegaPadre(Candidate, Candidate ->right, OldCandidate, Tree)

else

LegaPadre(Candidate, Candidate ->right, Parent, Tree);

P40

34

34

P40

38

P36

P34


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

500

600

400

700

450

800

420

460

900

410

430

480

470

455

475

454

456

Cancella un nodo

500

600

400

700

440

800

420

460

900

410

430

450

480

470

455

475

454

456


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

Cancella la root

500

550

400

600

400

600

550

564

564

553

566

553

566

558

558

556

559

556

559

555

557

555

557


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

A

B

C

D

E

F

G

H

ESERCIZIO

Sia assegnato un albero binario, scrivere un algoritmo tale che sposti ogni figlio sinistro nel corrispondente figlio destro e viceversa.

A

C

B

F

E

D

H

G


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

void ScambiaNodi(Tnodo Tree)

{Tnodo Temp;

if (Tree != NULL)

{

ScambiaNodi(Tree->left);

ScambiaNodi(Tree->right);

Temp=Tree->left;

Tree->left= Tree->right;

Tree->right=Temp;

};

};

post-order

albvari


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

A

A->right

A->left

A-> left -> right

A-> left ->left

/* Sviluppare una funzione che, assegnato un albero binario T,

conti quanti nodi sinistri, hanno come unico figlio un nodo foglia. */

int contafigli(Tnodo A)

{

if (A==NULL)

return 0;

else

{

if (

(

(A->left!=NULL)&&

(A->left->left==NULL)&&

(A->left->right==NULL)&&

(A->right==NULL)

)

)

{ cout<<" "<<A->key<<" ha come unico figlio un nodo foglia "<<endl;

return contafigli(A->left)+contafigli(A->right)+1;

}

else

return contafigli(A->left)+contafigli(A->right);

}

}

Albvari


Corso di programmazione ii lezione 19 operazioni sugli alberi prof e burattini a a 2009 2010

/* A1L08

Data una lista di interi eliminare un nodo ogni K incontrati. Nel caso il numero totale dei nodi non sia multiplo di K aggiungere quanti nodi servono per soddisfare questa condizione attribuendo ad essi una chiave di valore uguale a K.

*/

void provaA3L(Pnodo &TL, Pnodo L, int cont,int k, Pnodo prec)

{ Pnodo Temp;

if ((L==NULL)&&((cont-1)%k==0)) // se L non è finita e cont è mod k

return;

else

{ if (L!=NULL)

{

if (cont%k!=0) {

provaA3L(TL, L->next, cont+1, k, L);}

else

{

prec->next=L->next;

cout<<"cancello "<<L->info<<endl;

delete L;

provaA3L(TL, prec->next, 1, k, prec);

}

}

else

{

creaNodo(k,Temp);

prec->next=Temp;

provaA3L(TL, Temp->next, cont+1, k, Temp);

}}

}


  • Login