Esercizio: Trovare i due elementi più grandi di un Array

Esercizio

Vogliamo realizzare una funzione chiamata trova_due_elementi_maggiori.

Questa funzione ha come tipo di ritorno void e prende in ingresso i seguenti parametri:

  • Un array a di tipo double con i valori su cui operare;
  • Un intero n contenente il numero di elementi dell'array;
  • Un puntatore ad un double che conterrà il primo elemento più grande dell'array: max1;
  • Un puntatore ad un double che conterrà il secondo elemento più grande dell'array: max2.

La firma della funzione sarà:

void trova_due_elementi_maggiori(double a[], int n, double *max1, double *max2);

Implementazione

Proviamo ad implementare la funzione.

Dai requisiti descritti sopra la funzione utilizza due puntatori per restituire i risultati di massimo e secondo massimo dell'array. Inoltre, la funzione deve essere in grado di trovare i due elementi più grandi anche se questi sono uguali. Per esempio, se l'array è [1, 2, 3, 3] allora il massimo sarà 3 e il secondo massimo sarà 3. Se l'array è [1, 2, 3, 4] allora il massimo sarà 4 e il secondo massimo sarà 3.

Una possibile implementazione è la seguente:

void trova_due_elementi_maggiori(double a[], int n, double *max1, double *max2) {
    int i;

    /* Inizializza il massimo al primo elemento dell'array */
    *max1 = a[0];

    /* Inizializza il secondo massimo al secondo elemento dell'array */
    *max2 = a[1];

    /* Se il secondo massimo è maggiore del massimo, scambia i due valori */
    if (*max2 > *max1) {
        double tmp = *max1;
        *max1 = *max2;
        *max2 = tmp;
    }

    for (i = 2; i < n; ++i) {
        if (a[i] > *max1) {
            *max2 = *max1;
            *max1 = a[i];
        } else if (a[i] > *max2) {
            *max2 = a[i];
        }
    }
}

Da notare che abbiamo ottimizzato l'implementazione in quanto il massimo e il secondo massimo sono calcolati in un solo ciclo.

Un possibile problema in questa implementazione è che se l'array contiene meno di due elementi, il programma potrebbe non funzionare correttamente. Per esempio, se l'array contiene un solo elemento, allora il massimo sarà a[0] e il secondo massimo sarà a[1] che tuttavia non esiste. Per risolvere questo problema, possiamo aggiungere un controllo iniziale per verificare che l'array abbia almeno due elementi:

void trova_due_elementi_maggiori(double a[], int n, double *max1, double *max2) {
    int i;

    /* Se l'array contiene meno di due elementi, non fare nulla */
    if (n < 2) {
        return;
    }

    /* Inizializza il massimo al primo elemento dell'array */
    *max1 = a[0];

    /* Inizializza il secondo massimo al secondo elemento dell'array */
    *max2 = a[1];

    /* Se il secondo massimo è maggiore del massimo, scambia i due valori */
    if (*max2 > *max1) {
        double tmp = *max1;
        *max1 = *max2;
        *max2 = tmp;
    }

    for (i = 2; i < n; ++i) {
        if (a[i] > *max1) {
            *max2 = *max1;
            *max1 = a[i];
        } else if (a[i] > *max2) {
            *max2 = a[i];
        }
    }
}

Programma completo

Proviamo, adesso, a scrivere un programma che utilizza la funzione trova_due_elementi_maggiori per trovare i due elementi più grandi di un array di 10 elementi.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>

void trova_due_elementi_maggiori(double a[], int n, double *max1, double *max2);

int main() {
    const int N = 10;
    double max1, max2;
    double a[N];
    int i;

    /* Inizializza l'array leggendo i valori da tastiera */
    printf("Inserisci 10 valori: ");

    for (i = 0; i < N; ++i) {
        scanf("%lf", &a[i]);
    }

    /* Trova i due elementi più grandi */
    trova_due_elementi_maggiori(a, 10, &max1, &max2);

    /* Stampa i risultati */
    printf("Il massimo è %lf\n", max1);
    printf("Il secondo massimo è %lf\n", max2);

    return 0;
}

void trova_due_elementi_maggiori(double a[], int n, double *max1, double *max2) {
    int i;

    /* Se l'array contiene meno di due elementi, non fare nulla */
    if (n < 2) {
        return;
    }

    /* Inizializza il massimo al primo elemento dell'array */
    *max1 = a[0];

    /* Inizializza il secondo massimo al secondo elemento dell'array */
    *max2 = a[1];

    /* Se il secondo massimo è maggiore del massimo, scambia i due valori */
    if (*max2 > *max1) {
        double tmp = *max1;
        *max1 = *max2;
        *max2 = tmp;
    }

    for (i = 2; i < n; ++i) {
        if (a[i] > *max1) {
            *max2 = *max1;
            *max1 = a[i];
        } else if (a[i] > *max2) {
            *max2 = a[i];
        }
    }
}