Alberi binari di ricerca - Cancella nodo

di il
1 risposte

Alberi binari di ricerca - Cancella nodo

Salve sto svolgendo il seguente esercizio.
"Sia dato un ABR T, i cui nodi contengono esclusivamente un campo chiave figlio sx e un campo chiave figlio dx. Scrivere un algoritmo ricorsivo efficiente che cancelli dall'albero T tutti i nodi che stiano ad una profondità compresa tra i valori l1>=1 e l2 (dati in ingresso), le cui chiavi si trovino in posizione multipla di 3 nell'ordinamento totale delle chiavi. Tutte le condizioni da verificare si riferiscono all'albero originario fornito in ingresso.
Non è ammesso l'uso di passaggio di parametri per riferimento nè l'impiego di variabili globali."

Il mio codice è il seguente

main.c
#include <stdio.h>
#include <stdlib.h>
#include "abr.h"

int main()
{
    ABR T=NULL;
    int n,i,x;
    /*printf("Quanti elementi vuoi inserire?\n");
    scanf("%d",&n);
    printf("\n\nInserimento :\n");
    for(i=0; i<n; i++)
    {
        printf("- ");
        scanf("%d",&x);
        T=abr_insert(T,x);
    } INSERIMENTO MANUALE */

    //n=6;
    //int A[6]={10,12,5,3,11,18}; CASO D'USO 1

    n=7;
    int A[7]={10,12,5,3,7,11,18};

    for(i=0; i<n; i++)
        T=abr_insert(T,A[i]);

    system("PAUSE");
    printf("L'abr creato:\n");
    abr_stampa(T);

    int l1=1, l2=5;
    printf("\n\n");


    x=es_3(T,l1,l2,1);
    abr_stampa(T);


    system("PAUSE");
    return 0;

}
abr.h
#ifndef ABR_H_INCLUDED
#define ABR_H_INCLUDED

typedef struct abr * ABR;

ABR abr_insert(ABR t, int elem);
void abr_stampa(ABR t);
void abr_stampapreorder(ABR t);
void abr_stampapostorder(ABR t);
/*ABR abr_svuota (ABR t);*/

ABR abr_cancellaRic (ABR T, int k);
ABR abr_staccaMin(ABR T, ABR P);

ABR abr_cancellaNodoIter (ABR T, ABR P);
ABR abr_cancellaRadice (ABR T);

int es_3(ABR T, int l1, int l2, int pos);

#endif // ABR_H_INCLUDED
abr.c
#include <stdio.h>
#include <stdlib.h>
#include "abr.h"

typedef struct abr
{
    int info;
    struct abr * sx;
    struct abr * dx;
} abr;


ABR abr_insert(ABR t, int elem) {

    if (t!=NULL) {

        if (elem < (t->info))
            t->sx=abr_insert(t->sx,elem);
        else if (elem > (t->info))
            t->dx=abr_insert(t->dx,elem);

        return t;
    }

    else {
        ABR nodo=(abr *)malloc(sizeof(abr));
        nodo->info=elem;
        nodo->sx=NULL;
        nodo->dx=NULL;
        return nodo;
    }
}

void abr_stampa(ABR t)
{
     if (t!=NULL)
     {
        if (t->sx!=NULL) abr_stampa(t->sx);

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

        if(t->dx!=NULL) abr_stampa(t->dx);
        }

     else return;
}

void abr_stampapreorder(ABR t)
{
    if (t==NULL) return;
    printf("%d\n",t->info);
    abr_stampa(t->sx);
    abr_stampa(t->dx);
}
void abr_stampapostorder(ABR t)
{
    if (t==NULL) return;

    abr_stampa(t->sx);
    abr_stampa(t->dx);
    printf("%d\n",t->info);
}

ABR abr_cancellaRic (ABR T, int k)
{
    if (T!=NULL)
    {
        if(k<T->info)
            T->sx=abr_cancellaRic(T->sx,k);
        else if(k>T->info)
            T->dx=abr_cancellaRic(T->dx,k);
        else /*k=T->info*/
        {
            ABR nodo=(abr*)malloc(sizeof(abr));
            nodo=T;
            if(nodo->dx==NULL)
                T=nodo->sx;
            else if(nodo->sx==NULL)
                    T=nodo->dx;
            else
            {
                nodo=abr_staccaMin(T->dx,T);
                T->info=nodo->info;
                free(nodo);
            }

        }
    }

    return T;
}


int es_3(ABR T, int l1, int l2, int pos)
{
    printf("Sono nella funzione: pos = %d, k=%d\n",pos,T->info);
    if ((T->sx!=NULL) && (l2>0))
    {
        printf("T->sx!=NULL\n");
        pos=es_3(T->sx,l1,l2-1,pos); printf("Prima riga eseguita\n");
        pos=pos+1; printf("pos=%d\n",pos);
    }

    printf("\nPRIMA DELL'if: T=%d pos=%d l1=%d l2=%d\n",T->info,pos,l1,l2);
    if ((pos%3 ==0) && (l1<=l2))
    {
        printf("\nElimino %d perchè si trova alla posizione %d multiplo di 3, e alla profondita' %d\n",T->info,pos,5-l2);
        abr_cancellaRic(T,T->info);
        }


    if ((T->dx!=NULL) && (l2>0))
    {
        printf("T->dx!=NULL\n");
        pos++;
        return es_3(T->dx,l1,l2-2,pos);
    }

return pos;
}



 /*ABR abr_svuota (ABR t)
{

    if (t!=NULL)
    {
        t->sx=abr_svuota(t->sx);
        t->dx=abr_svuota(t->dx);

        t=abr_cancellanodo(t);
    }
return t;
}*/

ABR abr_cancellaNodoIter (ABR T, ABR P)
{
    if(P==NULL)
        return abr_cancellaRadice(T);

    if(T->sx==NULL) /*T ha UN SOLO figlio: destro*/
    {
        if(T==P->sx)
           P->sx=T->dx;
        else P->dx=T->sx;
    }
    else if(T->dx==NULL) /*T ha UN SOLO figlio: sinistro*/
    {
        if(T==P->sx)
            P->sx=T->dx;
        else P->dx=T->dx;
    }
    else /*T ha DUE figli*/
    {
        ABR nodo=(abr*)malloc(sizeof(abr));
        nodo=abr_staccaMin(T->dx,T);
        T->info=nodo->info;
        free(nodo);
    }

    return T;
}

ABR abr_staccaMin(ABR T, ABR P)
{
    if (T!=NULL)
    {
        if (T->sx!=NULL)
            return abr_staccaMin(T->sx,T);
        else if (T==P->sx)
                P->sx=T->dx;
            else
                P->dx=T->dx;
        }

    return T;
}

ABR abr_cancellaRadice (ABR T)
{
    if (T->sx==NULL)
        return T->dx;
    if (T->dx==NULL)
        return T->sx;

    ABR nodo=(abr*)malloc(sizeof(abr));
    nodo=abr_staccaMin(T->dx,T);
    free(nodo);

    return T;
}
Tralasciando i milioni di printf che mi servono per capire passo passo nell'esecuzione cosa sto facendo, poi li cancellerò. Pongo la vostra attenzione sulle sole funzioni es_3, abr_cancellaRic, abr_staccaMin. Quello che succede è che se svolgo l'esercizio con i dati commentati (//caso 1) funziona, se svolgo con i dati che invece non sono commentati non mi elimina il nodo con key 7, ma solo 12. Le funzioni di cancellazione mi sembrano corrette perchè le ho precedentemente provate. Credo l'errore sia nella mia funzione anche perchè nella riga di cancellazione dovrei scrivere T=cancella.... ma l'esecuzione si blocca.
Cosa ho combinato?
Grazie per la risposta

1 Risposte

Devi accedere o registrarti per scrivere nel forum
1 risposte