Funzione ricorsiva

di il
14 risposte

Funzione ricorsiva

Ciao a tutti, devo fare una funzione ricorsiva in C che ha come parametro di ingresso un insieme non vuoto e restituisce il suo valore massimo...è possibile farla con in ingresso solo un'array?

grazie!

14 Risposte

  • Re: Funzione ricorsiva

    Nessun'idea su come fare questa funzione?
    AIUTO!!
  • Re: Funzione ricorsiva

    Allora io ho provato a far una cosa del genere...è quasi un ordinamento e alla fine prende il primo elemento dell'array che è il più grande!
    int massimo(int *insieme)
        {
           int dim,tmp;
           dim=insieme[0];
           if (dim>1)
           {
                    if(insieme[dim]>insieme[dim-1])
                    {
                          
                          tmp=insieme[dim];
                          insieme[dim]=insieme[dim-1];
                          insieme[dim-1]=tmp;
                    }
                    
           insieme[0]=dim-1;
           massimo(insieme);
           }
           else 
           return(insieme[1]);
        }
     

    però quando lo richiamo nella main:
    max=massimo(insieme);
    printf("%d",max);
    mi stampa a video cose come:1982601220...dove sbaglio?

    Grazie mille!!
  • Re: Funzione ricorsiva

    Ciao, ti ho scritto un esempio in cui c'è la funzione ricorsiva che chiedi. Per qualsiasi cosa chiedi pure.
    
    /*
      * main.c
      *
      *  N.B: La funzione ricorsiva ha bisogno di avere la dimensione
      *          del vettore fissa, quindi ho dovuto utilizzare una
      *          variabile globale :(
      * Data : 26/04/2010
      */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    
    #define FLAG_ESCI   "ZZ"
    #define MAX_STR     (255)
    
    typedef enum { FALSE, TRUE } Bool;
    
    
    unsigned dimInsieme;
    
    /* Prototipi funzione */
    int* aggiungi_elemento  (int*, unsigned, int);
    void visualizza_insieme (int*, unsigned);
    int* valmax_insieme     (int*, unsigned);
    
    
    
    
    int main(int argc, char** argv) {
        Bool     bEsci;
        char     s[MAX_STR];
        unsigned nElem;
        int*     insieme;
        int      max;
    
    
        insieme = NULL;
        bEsci   = FALSE;
        nElem   = 0;
        while (!bEsci) {
            printf("# Elemento %d - [%s per uscire]: ",nElem,FLAG_ESCI);
            scanf("%s%*c",s);
    
            if (!strcmp(s,FLAG_ESCI)) bEsci = TRUE;
            else
                insieme = aggiungi_elemento(insieme,nElem++,atoi(s));
        }
    
        printf("\n\n[-] Insieme:\n");
        visualizza_insieme(insieme,nElem);
    
        /* Valore massimo nell'insieme */
        dimInsieme = nElem;
        max        = *valmax_insieme(insieme,nElem);
        printf("\n[-] Valore massimo => %d",max);
    
        free(insieme);
        return 0;
    }
    
    
    
    /* Descrizione : Aggiunge un elemento nell'insieme. */
    int* aggiungi_elemento(int* insieme, unsigned nElem, int elem) {
        if (!(insieme = realloc(insieme,(nElem + sizeof(int)) * sizeof(int)))) {
            fprintf(stderr,"%s",strerror(errno));
            exit(-1);
        }
    
        *(insieme + nElem) = elem;
        return insieme;
    }
    
    
    /* Descrizione : Mostra su stdout l'insieme numerico inserito. */
    void visualizza_insieme(int* insieme, unsigned n) {
        unsigned i;
    
        for (i = 0; i < n; i++)
            printf("[%d] => %d\n",i,*(insieme + i));
    }
    
    
    /* Descrizione : Funzione ricorsiva che ritorna l'elemento di valore
     *               massimo. */
    int* valmax_insieme(int* insieme, unsigned n) {
        static unsigned iposmax = 0;
        int* primoElemento    = insieme - (dimInsieme - n);
        int  max              = *(primoElemento + iposmax);
    
        if (n == 1) return primoElemento + iposmax;
        if (max < *(insieme+1)) iposmax = dimInsieme - (n - 1);
    
        return valmax_insieme(insieme+1,n-1);
    }
    
    
    In questo modo la funzione "valmax_insieme" ritorna l'elemento con valore massimo all'interno dell'insieme numerico, il tutto senza ordinare (o modificare) il vettore di partenza.
    L'unica cosa e' che io gli passo l'indirizzo "originale" del vettore, in questo modo al termine della ricerca del valore maggiore il puntatore "insieme" puntera' all'ultimo elemento, quindi conviene o passargli una copia del vettore oppure al termine della ricorsione (if <n> == 1) ripristinare il puntatore "insieme" al suo valore iniziale, modificando con una cosa del tipo:
    
    if (n == 1) {
       insieme = primoElemento;
       return primoElemento + iposmax;
    }
    
    In ogni caso vedi tu di adattarlo in base alle necessita'.
    Saluti, netburst.
  • Re: Funzione ricorsiva

    Grazie mille netburst, ma a me serve una funzione che abbia come parametro d'ingresso il solo insieme, mentre tu passi anche "n".

    Potresti dare un'occhiata a quella che ho scritto io per capire perchè mi restituisce quel numero invece del valore massimo?

    Io nella main se invece di stampare max stampo insieme[1], il valore che mi stampa è il valore massimo, allora perchè max non prende il valore di insieme[1]?

    grazie ancora! Ciao
  • Re: Funzione ricorsiva

    La funzione che hai fatto l'ho provata ma non mi funziona ne' se stampo "max" ne' se stampo "insieme[1]".
    Comunque una funzione che ha il compito di trovare il valore massimo tra un insieme di numeri non dovrebbe, anzi direi che non deve, ordinare l'insieme in questione, ma deve fare solamente cio' per cui e' stata implementata, quindi ricerca e restituzione dell'elemento massimo.
    Se a te occorre una serie numerica ordinata ti conviene farti una funzione a parte.

    Per quanto riguarda la tua funzione "massimo".
    Seguiamo istruzione per istruzione come farebbe un debugger.
    Facciamo un esempio in cui il vettore "insieme" e' formato da 3 elementi quindi 0, 1 e 2
    che contengono rispettivamente i valori 7 4 2.
    
    int massimo(int* insieme) {
        int dim;
        int tmp;
    
        dim = insieme[0];
        if (dim > 1) {
        	if(insieme[dim] > insieme[dim-1]) {
    	    tmp		   = insieme[dim];
    	    insieme[dim]	   = insieme[dim-1];
                insieme[dim-1]  = tmp;
            }
            
    	insieme[0] = dim - 1;
            massimo(insieme);
        } else
          	return(insieme[1]);
    }
    
    Prima chiamata alla funzione "massimo":
    
    	dim = insieme[0];	// dim = 7
    	if (dim > 1)	    // dim = 7 quindi entra nell' if
    	if (insieme[7] > insieme[7 - 1])	// ERRORE: il nostro vettore ha solo 3 elementi!
    
    Questo e' sicuramente una causa del problema
    Saluti, netburst.
  • Re: Funzione ricorsiva

    Scusami, mi sono scordato di dire che sulla prima locazione di memoria dell'array (insieme[0]) io inserisco la dimensione dell'insieme.

    Quindi nell'esempio che hai fatto tu 3 elementi(creo l'insieme da 4 elemnti e nel primo inserisco 3):
    diciamo 2 4 7
     dim = insieme[0];   // dim = 3
       if (dim > 1)       // dim = 3 quindi entra nell' if
       if (insieme[3] > insieme[3 - 1])   // 7>4 (entra nellìf)
           tmp                   = insieme[dim];   //tmp=7
           insieme[dim]      = insieme[dim-1]; //insieme[3]=4
           insieme[dim-1]   = tmp; //insieme[2]=7
            }
           
       insieme[0] = dim - 1;  //insieme[0]=2
            massimo(insieme); // e via così fino ad avere il massimo su insieme[1]
        } else
             return(insieme[1]);
    Spero di essermi spiegato ora.

    il fatto è che è un progetto d'esame e il prof ci ha messo il vincolo di usare come parametro d'ingresso solo l'insieme, senza altri dati, e di fare una funzione ricorsiva, quindi non so come fare!

    ciao e grazie ancora!
  • Re: Funzione ricorsiva

    Allora, il problema è nella return secondo me perchè se nella main invece di:
    max=massimo(insieme);
    printf("%d",max);
    Metto:
      max=insieme[1];
      printf("%d",max);
    Il programma funziona, perchè il massimo, dopo la funzione, è contenuto su insieme[1].

    ma a me serve che restituisca il massimo, sbaglio qualcosa sulle dichiarazioni delle variabili?
    non so?!? aiutatemi!

    ciao!
  • Re: Funzione ricorsiva

    j4m3s ha scritto:


    Allora, il problema è nella return secondo me perchè se nella main invece di:
    max=massimo(insieme);
    printf("%d",max);
    Metto:
      max=insieme[1];
      printf("%d",max);
    Si, e' la funzione "massimo" non la chiami piu'?! -.-"
    Comunque, io non capisco molto il senso di questa cosa, se puoi spostare gli elementi del vettore come ti pare e piace fatti un ordinamento decrescente ed avrai alla posizione di indice 1 (se ad indice 0 hai la dimensione dell'insieme) il valore massimo. Se cosi' puo' andare il problema cambia: non devi cercare il massimo valore, ma fare un algoritmo per l'ordinamento decrescente in modo ricorsivo.
    Poi un'altra cosa, avere la dimensione dell'insieme alla posizione del vettore, contenente l'insieme stesso, di indice 0 fa parte delle specifiche di progetto o e' una tua idea?
    Saluti, netburst.
  • Re: Funzione ricorsiva

    Il fatto che io non chiami più la funzione era solo per dimostrare che in insieme[1] c'era il massimo!

    Il problema non dice che in insieme[0] ci debba essere la dimensione ma era un'idea mia per risolvere un po' di problematiche...ti posto il problema per intero:
    Scrivere una libreria ANSI C che gestisce insiemi di numeri interi esportando le seguenti cinque funzioni. La prima funzione restituisce un insieme acquisito da tastiera. La seconda funzione ha come parametro di ingresso un insieme e lo stampa a video. La terza funzione ha come parametro di ingresso un insieme non vuoto e restituisce il suo valore mediano. La quarta funzione ha come parametro di ingresso un insieme non vuoto e restituisce il suo valore massimo, il quale deve essere calcolato ricorsivamente. La quinta funzione ha come parametro di ingresso un insieme non vuoto e restituisce il suo valore minimo, il quale deve essere calcolato ricorsivamente.
    Il passare in insieme[0] la dimensione era per risolvere il problema di creare una funione ricorsiva che trovasse il massimo (o il minimo) avente come input solo l'insieme!

    Forse sbaglio ad usare anche gli array...non so!

    Scusa il disturbo ma è importante!

    Ciao!
    J4m3s
  • Re: Funzione ricorsiva

    j4m3s ha scritto:


    Il fatto che io non chiami più la funzione era solo per dimostrare che in insieme[1] c'era il massimo!
    Se non chiamando la funzione in insieme[1] trovi il massimo e' puramente casuale. Se ad esempio, l'input e': 9 8 7 (insieme[0] = 3) si, in insieme[1] hai il valore massimo; ma se l'input e': 7 8 5 in insieme[1] non hai piu' il massimo. Proprio per questo motivo la funzione "massimo" deve per forza essere chiamata.

    Dato che deve essere una libreria deve essere scritta bene quindi le funzioni sull'insieme (max, min, media ecc...) non devono modificarlo e nemmeno scambiarne i valori.
    Ora che ho il testo intero, ci penso e vedo se riesco a fare qualcosa, mi dispiace di non poterti essere subito di aiuto ma con la ricorsione faccio una fatica incredibile
    Saluti.
  • Re: Funzione ricorsiva

    Ciao, questa e' la soluzione che propongo:
    
    /*
     * insieme.c
     *
     * Descrizione : Routines per la gestione di un insieme di integer.
     *               L'insieme viene terminato con il terminatore TERMINA_INSIEME.
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    
    #include "insieme.h"
    
    #define MAX_BUFF        (255)
    #define TERMINA_INSIEME 'Z'
    
    
    typedef enum { FALSE, TRUE } Bool;
    
    
    
    /* Prototipi funzioni private */
    static int* add_elemento (int*, unsigned, int);
    
    
    
    
    /*
     * extern int* Insieme_input(void);
     *
     * Descrizione       : Input di un insieme da tastiera.
     * Parametri         : void
     * Valore di ritorno : Indirizzo del primo elemento dell'insieme.
     * Data              : 28/04/2010
     */
    extern int* Insieme_input(void) {
        Bool     end;
        unsigned nElem;
        int*     v;
        char     s[MAX_BUFF];
    
        end   = FALSE;
        nElem = 0;
        v     = NULL;
    
        while (!end) {
            printf("[-] Elemento %d: ",nElem + 1);
            fgets(s,sizeof(s) - 1,stdin);
    
            if (s[0] == '\n') end = TRUE;
            else
                v = add_elemento(v,nElem++,atoi(s));
        }
    
        /* La gestione interna dell'insieme e' mia quindi lo termino come voglio */
        v = add_elemento(v,nElem,TERMINA_INSIEME);
        return v;
    }
    
    
    /*
     * extern void Insieme_output(const int* insieme);
     *
     * Descrizione       : Output su video di un insieme.
     * Parametri         : Indirizzo del primo elemento dell'insieme.
     * Valore di ritorno : void
     * Data              : 28/04/2010
     */
    extern void Insieme_output(const int* insieme) {
        unsigned n;
    
        for (n = 0; *(insieme + n) != TERMINA_INSIEME; ++n)
            printf("[-] Elemento %d => %d\n",n + 1,*(insieme + n));
    }
    
    
    /*
     * extern int Insieme_mediano(const int* insieme);
     *
     * Descrizione       : Cerca e restituisce il valore mediano dell'insieme
     *                     NON vuoto.
     * Parametri         : Indirizzo del primo elemento dell'insieme.
     * Valore di ritorno : Valore mediano dell'insieme.
     * Data              : 28/04/2010
     */
    extern int Insieme_mediano(const int* insieme) {
        unsigned dim;
        int      mediano;
        int      m1;
        int      m2;
    
        for (dim = 0; *(insieme + dim) != TERMINA_INSIEME; ++dim)
            ;
    
        if (dim % 2) mediano = (dim + 1) / 2;
        else {
            m1      = dim / 2;
            m2      = (dim / 2) + 1;
            mediano = (m1 + m2) / 2;
        }
    
        return *(insieme + --mediano);
    }
    
    
    /*
     * extern int Insieme_massimo(const int* insieme);
     *
     * Descrizione       : Cerca e restituisce il valore massimo dell'insieme
     *                     NON vuoto.
     * Parametri         : Indirizzo del primo elemento dell'insieme.
     * Valore di ritorno : Valore massimo dell'insieme.
     * Data              : 28/04/2010
     */
    extern int Insieme_massimo(const int* insieme) {
        static unsigned ipos = 0;
        static int max       = INT_MIN;
    
        if (*(insieme + ipos) != TERMINA_INSIEME) {
            if (max < *(insieme + ipos)) max = *(insieme + ipos);
            ++ipos;
            return Insieme_massimo(insieme);
        }
    
        return max;
    }
    
    
    /*
     * extern int Insieme_minimo(const int* insieme);
     *
     * Descrizione       : Cerca e restituisce il valore minimo dell'insieme
     *                     NON vuoto.
     * Parametri         : Indirizzo del primo elemento dell'insieme.
     * Valore di ritorno : Valore minimo dell'insieme.
     * Data              : 28/04/2010
     */
    extern int Insieme_minimo(const int* insieme) {
        static unsigned ipos = 0;
        static int min       = INT_MAX;
    
        if (*(insieme + ipos) != TERMINA_INSIEME) {
            if (*(insieme + ipos) < min) min = *(insieme + ipos);
            ++ipos;
            return Insieme_minimo(insieme);
        }
    
        return min;
    }
    
    
    /*
     * extern void Insieme_cancella(int* insieme);
     *
     * Descrizione       : Cancella, liberando la memoria occupata, l'insieme.
     * Parametri         : Indirizzo del primo elemento dell'insieme.
     * Valore di ritorno : void
     * Data              : 28/04/2010
     */
    extern void Insieme_cancella(int* insieme) {
        free(insieme);
    }
    
    
    
    
    /* ******************* Implementazione funzioni private ******************** */
    
    static int* add_elemento(int* v, unsigned n, int val) {
        if (!(v = realloc(v,(n + sizeof(int)) * sizeof(int)))) {
            perror("realloc()");
            exit(-1);
        }
    
        *(v + n) = val;
        return v;
    }
    
    Come si puo' vedere nell'indice 0 (zero) del vettore non inserisco la dimensione dell'insieme, per poter determinare la fine dell'insieme lo termino con un valore arbitrario (TERMINA_INSIEME), un po' come fa il C per determinare la fine di una stringa ('\0').
    La funzione "Insieme_input" prende da stdin elemento per elemento fino a quando non si inserisce un elemento nullo, cioe' si preme solamente il tasto INVIO.

    Dato che deve essere una libreria il suo header e':
    
    #ifndef INSIEME_H_
    #define INSIEME_H_
    
    #ifdef __cplusplus
        extern "C" {
    #endif
    
    extern int* Insieme_input    (void);
    extern void Insieme_output   (const int*);
    extern int  Insieme_mediano  (const int*);
    extern int  Insieme_massimo  (const int*);
    extern int  Insieme_minimo   (const int*);
    extern void Insieme_cancella (int*);
    
    #ifdef __cplusplus
        }
    #endif
    #endif /* INSIEME_H_ */
    

    Le funzioni della libreria possono essere usate in modo simile a questo:
    
    int main(void) {
        int* v;
    
        v = Insieme_input();
    
        printf("\nElementi dell'insieme:\n");
        Insieme_output(v);
    
        printf("\nElemento di valore massimo => %d\n",Insieme_massimo(v));
        printf("Elemento di valore minimo      => %d\n",Insieme_minimo(v));
        printf("Valore elemento mediano        => %d\n",Insieme_mediano(v));
    
        Insieme_cancella(v);
        return 0;
    }
    

    Questa volta credo (e sperto) di aver rispettato tutte le consegne
    Saluti, netburst.
  • Re: Funzione ricorsiva

    Perfetto!!!
    grazie mille! Ti sono debitore!!!
  • Re: Funzione ricorsiva

    Di niente, fammi sapere il voto che ti da il prof per questa esercitazione.
    Saluti.
  • Re: Funzione ricorsiva

    netburst ha scritto:


    Di niente, fammi sapere il voto che ti da il prof per questa esercitazione.
    Saluti.
    Molto utile forum thread ho utilizzerà questo
Devi accedere o registrarti per scrivere nel forum
14 risposte