[snip]
C'è una soluzione un po' più elegante, senza bisogno di riscrivermi una
funzione quicksort apposita?
[snip]
Una delle cose che potresti decidere di fare e` ordinare gli elementi
appena questi vengono acquisiti (letti da regular file, user input, ecc.
ecc.) durante la scrittura nell'array di strutture. Realizzare cio` con un
array allocato staticamente e` un attentato alla pazienza di chiunque
(overkill swap). La cosa piu` semplice da implementare e` una lista
linkata. Ti ho scritto un esempio qui di sotto che non realizza
esattamente cio` che vuoi, ma ti fornisce una traccia; in sostanza
cambiando poche righe di codice ottieni cio` che desideri ;)
Quest'esempio inserisce *tutti* i numeri dati in ordine crescente
(comprese le possibili ripetizioni); nel tuo post non c'erano riferimenti
su come gestire questa situazione per cui qui vengono semplicemente
aggiunti. Se desideri non inserirli o se hai un contatore di occorrenze,
ti basta cambiare poche righe di codice per ottenere il comportamento
voluto ;)
Essendo una lista semplicemente linkata ottieni, come "vantaggio
collaterale", un'estrema semplicita` nel rimuovere un singolo elemento.
L'eventuale funzione che implementa questa operazione e` pressoche` uguale
alla __add_member ;)
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef NUM_TEST_KEYS
# define NUM_TEST_KEYS 20
#endif
#ifndef MIN_KEY_VALUE
# define MIN_KEY_VALUE 1
#endif
#ifndef MAX_KEY_VALUE
# define MAX_KEY_VALUE 100
#endif
typedef struct my_element *array_t;
struct my_element
{
int key;
array_t next;
};
static __inline__ int __add_member(int curr_key, array_t *array)
{
array_t tmp = NULL, scan = NULL, prescan = NULL;
if ((tmp = calloc(1, sizeof(struct my_element))) == NULL)
return 0;
tmp->key = curr_key;
if (*array == NULL || (*array)->key >= curr_key)
{
tmp->next = *array;
*array = tmp;
}
else
{
for (prescan = *array, scan = (*array)->next;
scan != NULL && scan->key < curr_key;
prescan = scan, scan = scan->next);
tmp->next = scan;
prescan->next = tmp;
}
return 1;
}
static __inline__ void __print_array(array_t array)
{
(void)fprintf(stdout, "- Current array: ");
for (; array != NULL; array = array->next)
(void)fprintf(stdout, "%d ", array->key);
(void)fprintf(stdout, "\n");
}
static __inline__ void __delete_array(array_t *array)
{
if (*array != NULL)
{
__delete_array(&(*array)->next);
(*array)->key = 0;
free(*array);
*array = NULL;
}
}
int main(void)
{
int test_keys[NUM_TEST_KEYS];
array_t array = NULL;
int i;
(void)fprintf(stdout, "- Generating %d pseudo-random keys ... ",
NUM_TEST_KEYS);
srand(time(NULL));
for (i = 0; i < NUM_TEST_KEYS; i++)
/* yeah, do a crapping generation ;) */
test_keys[i] = MIN_KEY_VALUE + (rand() % MAX_KEY_VALUE);
(void)fprintf(stdout, "done.\n\n");
for (i = 0; i < NUM_TEST_KEYS; i++)
{
(void)fprintf(stdout, "- Add key %d ...\n", test_keys[i]);
if (!__add_member(test_keys[i], &array))
{
(void)fprintf(stderr, "*** fatal error: __add_member: errno %d
(%s)\n", errno, strerror(errno));
break;
}
__print_array(array);
}
__delete_array(&array);
return 0;
}
Il codice di cui sopra genera in maniera barbara (ma in questa sede non ci
interessa poi molto) una sequenza di NUM_TEST_KEYS (default = 20) keys
pseudo-random comprese nell'intervallo chiuso MIN_KEY_VALUE (default = 1)
e MAX_KEY_VALUE (default = 100); questa parte di codice e`
*esclusivamente* a scopo di test per simulare un eventuale input reale
(che tu avrai da regular file, user input, ecc. ecc. come dicevo prima).
Se desideri modificare i valori di default per i test ti basta passare le
opportune direttive di preprocessore a compile time (senza toccare il
codice); ad esempio, utilizzando gcc, se desideri generare 30 keys
anziche` 20:
gcc -DNUM_TEST_KEYS=30 -W -Wall -pedantic -ansi -o test test.c
A questo punto inizia il programma vero e proprio e, di conseguenza,
quello che interessa a te ;)
Come dicevo prima questo codice vuole essere una traccia; nella funzione
__add_member invece di passare solo la chiave dovrai passare la struttura
corrente ... ;)
Se prevedi di avere un'elevata mole di keys probabilmente dovresti
prendere in considerazione l'idea di implementare quest'idea con un albero
binario (magari sempre bilanciato) ... gestendo in maniera opportuna le
ripetizioni, ovviamente ;)
Ciao.
--
questo articolo e` stato inviato via web dal servizio gratuito
http://www.newsland.it/news segnala gli abusi ad ***@newsland.it