[C] Esercizio sui vettori

Obidream
Buonasera a tutti, con mio sommo dispiacere devo scomodarvi per una questione abbastanza banale, la quale però mi tiene bloccato in un esercizio più complesso :)
Sostanzialmente dovrei stampare a video un "dato statistico" su tutti gli elementi del vettore.
Ad esempio se avessi questo vettore:
int array[]={6,7,8,6,6}
Vorrei poter dire:
L'elemento 6 compare 3 volte
L'elemento 7 compare 1 volte
L'elemento 8 compare 1 volte

Mentre quel che sono riuscito ad ottenere col codice seguente è:
L'elemento 6 compare 3 volte
L'elemento 7 compare 1 volte
L'elemento 8 compare 1 volte
L'elemento 6 compare 3 volte
L'elemento 6 compare 3 volte

Il fatto che non funzioni non mi stupisce ( è ovvio che consideri più volte l'elemento 6 per come è scritto), però non riesco a trovare una soluzione efficace... Quindi mi serve il vostro aiuto, se possibile.

#include <stdio.h>
#include <string.h>
#define N 5

int main()
{
int array[]={6,7,8,6,6};
int i,cont,p;
cont=i=0;
while(i<N)
    {
    cont=0;
    for(p=0;p<N;p++)
        if(array[i]==array[p])
            cont++;
    printf("L'elemento %d compare %d volte\n",array[i],cont);
    i++;
    }
return 0;
}

Risposte
vict85
Il modo forse più ‘banale’, anche se forse non computazionalmente efficiente consiste nel riordinare i dati e poi contare le ripetizioni nel modo banale.

Un modo alternativo consiste nel memorizzare i valori già inseriti (in un albero, in una lista o in un array).

Un modo ancora alternativo potrebbe essere quello di controllare se array è presente prima di i.

In generale l'algoritmo scelto dipende dai tuoi scopi e da quanto sono grandi i numeri.

Obidream
Grazie per la risposta, si tratta di numeri comunque piccoli, quindi diciamo pure che un algoritmo vale l'altro a livello computazionale.. Potresti spiegare meglio il secondo metodo ( memorizzare i valori in un array) ed il terzo (controllare se array è presente prima di i)?

apatriarca
Un algoritmo molto facile è quello di definire un secondo vettore lungo quanto il primo e che possa contenere solo valori uguali a 0 o 1 (è sufficiente il tipo char ma va bene qualsiasi tipo intero). Per prima cosa inizializzi tutti gli elementi del vettore a zero. Dopodiché iteri sul tuo primo array. Ogni volta che il corrispondente elemento del secondo array è uguale a 0, iteri nel resto dell'array e conti il numero di occorrenze settando i valori del secondo array a 1 in modo da non considerarli nuovamente. Questo metodo restituisce i valori ordinati in base alla prima occorrenza di un particolare valore nell'array.

Se li vuoi ordinati può convenire inserire gli elementi in un secondo array che mantieni ordinato. Questo secondo array conterrà sia i valori, sia un contatore per ogni valore. Per ogni elemento del primo array verifichi se il valore è presente nel secondo. Se è presente incrementi il contatore, se non lo è aggiungi questo nuovo elemento all'array con contatore uguale a 1. Una versione alternativa di questa quando l'insieme dei valori possibili nell'array non è grande (supponi per esempio il caso di un file di testo) è quella di costruire un array in cui utilizzi i valori del primo array come indici nel secondo e questo secondo array memorizza solo i contatori. Usando questo secondo array il tuo algoritmo diventa lineare.

Immagino che nel terzo algoritmo l'idea fosse semplicemente quella di iterare l'intero array in cerca di copie dell'attuale elemento preso in considerazione. Se questo elemento compare per un indice minore di quello corrente allora può essere ignorato, in caso contrario si contano tutte le copie con indici maggiori o uguali a quello corrente.

Obidream
Credo che questo funzioni correttamente, grazie per l'aiuto :)
Sostanzialmente ho usato il suggerimento di Vict, ovvero memorizzare in tmp gli elementi già inseriti e poi usare un flag per vedere se è un elemento di cui ho già calcolato le occorrenze.

#include <stdio.h>
#include <stdlib.h>
#define N 5

int main()
{
int array[N];
int tmp[N];
int N_tmp;
int i,j,t;
int flag;
int cont;
for(i=0;i<N;i++)
    {
    printf("Inserisci l'elemento %d: ",(i+1));
    scanf("%d",&array[i]);
    }
N_tmp=0;
for(i=0; i<N; i++ )
    {
    flag=0;
    for(j=0;j<(N_tmp&&flag==0); j++ )
        if(tmp[j]==array[i])
            flag=1;
    if(flag==0)
        {
        tmp[N_tmp]=array[i] ;
        N_tmp++;
        cont=0;
        for (t=0;t<N;t++ )
            if(array[t]==array[i])
                cont++;
        if(cont==1)
            printf("%d compare %d volta\n",array[i],cont);
        else
            printf("%d compare %d volte\n",array[i],cont);
        }
    }
return 0;
}

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.