Traduzione dal Pascal al C di alcuni programmi di: “Fondamenti di

Traduzione dal Pascal al C di alcuni programmi di:
“Fondamenti di programmazione dei calcolatori elettron
Batini, Aiello, Lenzerini, Marchetti, Miola
INDICE
Argomento
Ricorsione
Matrici
Liste
Programma
Pagina Pagina del testo
Fattoriale
2
87
Rappresentazione compatta
3
107, 108, 109
Rappresentazione sequenziale
6
115-117
Rappresentazione collegata con array
9
126-127
Rappresentazione collegata con puntatori
12
128-131
Pile
Rappresentazione sequenziale
17
149
Rappresentazione collegata con puntatori
19
150
Code
Rappresentazione collegata con puntatori
21
152-153
Alberi binari Rappresentazione collegata con puntatori
23
162-166
Correttezza
Triangolo errato
27
242
Ricerca binaria
28
248
Complessità
Polinomio: quadratico e lineare 29
291, 292
Ordinamento
Selection sort
31
296-297
Bubble sort
32
299
Merge sort
34
303, 306
Ricorsione
Fattoriale: Funzione ricorsiva per il calcolo del fattoriale di un numero
#include <stdio.h>
int fattoriale(int n)
{
if (n==0) return 1;
else return n*fattoriale(n-1);
}
main()
{
int n;
/* lettura di n */
scanf("%d",&n);
/* display del fattoriale */
printf("%d!=%d\n",n,fattoriale(n));
}
Funzioni
In C non esistono procedure ma solo funzioni che devono essere dichiarate
<dich.funzione> static
[ ] [<tipo>] <identificatore>
([<lista-parametri>])
<blocco C>
es:
int
fat
Le funzioni
static
sono visibili solo nel file in cui sono dichiarate.
Il valore della funzione viene restituito
return
tramite
e non
l’istruzione
con un’assegnazione
all’identificatore della funzione come per il Pascal. La forma EBNF è:
<istruz.-return>
return
[ <espressione>
;
]
es:
return n*fattoriale(n-1);
If-then-else, operatori relazionali e booleani
La sintassi dell’istruzione
del C è: if
<istruzione-if>
if ( <espressione> ) <istruzione 1>; else <istruzion
es:
if
(n==0)
return 1;
L’espressione può essere composta tramite operatori relazionali:
== uguale,
!= diverso,
> maggiore, < minore,
maggiore
>=
o uguale,
<= minore o uguale
e operatori logici:
&& AND, || OR,
! NOT,& AND bit a bit, | OR bit a bit, ^ XOR bit a bit.
Direttiva #include<stdio.h>
Permette di usare le funzioni di I/O scanf e printf
• int scanf( const char *s, X1, X2, ... Xn)1: legge da standard input n
variabili. La stringa s formatta l’input, X1…Xn sono i puntatori alle
es:
scanf(“%d”,&n);
legge un valore intero (“%d”) e lo assegna alla
• int printf( const char *s, X1, X2, … Xn): stampa il valore di n variab
secondo la formattazione in s. es: printf("%d!=%d\n",n,fattoriale(n))
per n=5 stampa: 5!=120.
1
Per il significato degli operatori * e & vedere a pag. 8
2
Matrici
Rappresentazione compatta: La rappresentazione compatta di una matr
memorizzare matrici Queste
sparse. hanno la gran parte degli elementi uguali
prefissato detto valore predominante
per cui risulta conveniente memorizzare solo
diversi da tale valore. A tale scopo si usa un array di elementi c
informazioni: l’indice di riga, di colonna ed il valore. Il primo elemen
1 in Pascal) contiene il numero di righe della matrice, il numero
predominante. Le componenti dell’array non utilizzate vengono riempit
colonna non appartenenti alla matrice. Di seguito viene mostrata l’imple
dato matrice compatta e delle funzioni accedi e memorizza. Nel main si e
esemplificative a tali funzioni.
#include <stdio.h>
#define NMAX_COMPATTA 10
/* NMAX_COMPATTA-2 È il numero massimo
degli elementi diversi dall'elemento
predominante */
/* definizione del tipo matrice compatta */
typedef struct elem_mat_compatta
{
int riga, colonna;
int valore;
};
typedef struct elem_mat_compatta tipo_mat_compatta[NMAX_COMPATTA];
/* realizza l'operazione accedi su una matrice rappresentata
mediante la matrice compatta c a tre informazioni.
i È la riga, j la colonna
*/
int accedi(tipo_mat_compatta c,int i,int j)
{
int h;
h=1;
while (c[h].riga<i) h=h+1;
while (c[h].riga==i && c[h].colonna<j) h=h+1;
if (c[h].riga==i && c[h].colonna==j) return c[h].valore;
else return c[0].valore;
}
/* realizza l'operazione memorizza su una matrice
rappresentata mediante la matrice compatta c a
tre informazioni. i È la riga, j la colonna e val il
valore da memorizzare */
void memorizza (tipo_mat_compatta c,int i, int j, int val)
{
int h,q;
h=1;
Continua
while (c[h].riga<i) h=h+1;
3
while (c[h].riga==i && c[h].colonna<j) h=h+1;
/* controllo sul valore val da memorizzare */
if (val==c[0].valore)
{
if (c[h].riga==i && c[h].colonna==j)
/* elimina elemento di c in posizione h */
for(q=h+1;q<NMAX_COMPATTA;q++)
{
c[q-1].riga=c[q].riga;
c[q-1].colonna=c[q].colonna;
c[q-1].valore=c[q].valore;
}
}
else
if (c[h].riga==i && c[h].colonna==j) c[h].valore=val;
else /*se c'È posto memorizza il nuovo elemento in c*/
if (c[NMAX_COMPATTA-2].riga<=c[0].riga)
printf("memorizzazione impossibile\n");
else
{
for(q=NMAX_COMPATTA-2;q>=h+1;q--)
{
c[q].riga=c[q-1].riga;
c[q].colonna=c[q-1].colonna;
c[q].valore=c[q-1].valore;
}
c[h].riga=i;
c[h].colonna=j;
c[h].valore=val;
}
}
main()
{
tipo_mat_compatta mat;
int l;
/* inizializzazione prima riga dell'array con righe, colonne
e valore predominante */
mat[0].colonna=3;
mat[0].riga=3;
mat[0].valore=0;
/* inizializzazione dei restanti elementi ad una terna che non
corrisponde a nessuna componente della matrice es:10 */
for(l=1;l<NMAX_COMPATTA;l++)
{
mat[l].riga=10;
mat[l].colonna=10;
mat[l].valore=0;
Continua
}
4
/* memorizzazione valori */
memorizza(mat,2,2,5);
memorizza(mat,1,1,3);
memorizza(mat,1,2,7);
memorizza(mat,1,3,9);
/* display array */
printf("display array:\n");
for(l=0;l<NMAX_COMPATTA;l++) printf("%d %d %d
%d\n",l,mat[l].riga,mat[l].colonna,mat[l].valore);
/* display di alcuni valori della matrice */
printf("elem 2,2 %d\n",accedi(mat,2,2));
printf("elem 1,1 %d\n",accedi(mat,1,1));
printf("elem 2,1 %d\n",accedi(mat,2,1));
}
Definizioni di costanti in C
Uno dei metodi in C per definire delle costanti#define
è utilizzare
la direttiva
. Nel programma
si usa tale direttiva per definire la costante NMAX_COMPATTA. Altri esemp
#define PI 3.14, #define NOME “sabrina”, #define a_capo ‘\n’.
Definizione di tipi in C
Come in Pascal anche in C è possibile definire dei tipi di dati.
typedef.
In C si
Semplificando e rimandando ad un manuale C per la forma EBNF della dichia
si può dire che se in Pascal scriviamo ad esempio “type matricola = integ
C è “typedef int matricola;”.
Record e strutture
struct.
Il tipo record in Pascal ha il suo analogo C nel tipo struttura
per cui s
Le differenze nella sintassi tra C e Pascal possono essere notate confro
tipo della matrice compatta all’inizio di questo programma e la dichiaraz
testo.
Funzioni void
La funzione
memorizza in realtà svolge il ruolo di una procedura Pascal ovve
nessun valore. In tutti i casi in cui è necessario un simile comportament
parola chiave void prima dell’identificatore della funzione. (es: void me
Cicli For
In questo programma vengono utilizzati vari cicli for la cui sintassi in
<istr.-for>
for [<expr1>];
(
[<expr2>]; [<expr3>])
<istruzione>
<expr1>= insieme di assegnazioni separate da virgole per inizializzare la
del ciclo.
<expr2>=il ciclo viene eseguito finchè il valore di <expr2> è diverso da
<expr3>=è l’espressione che implementa la variazione delle variabili di c
es: for( l=0; l<NMAX_COMPATTA; l++)
imposta l=0 ed esegue il ciclo incrementando l di 1 (l++) ad ogni iterazi
l<NMAX_COMPATTA.
5
Liste
Rappresentazione sequenziale: Una lista può essere rappresentata mediante
componente ospita un elemento della lista. Dato che la dimensione della l
dinamico, sono necessarie due variabili (primo
per mantenere
e lunghezza)
sempre aggiornati
confini della lista. Di seguito è mostrata l’implemementazione in C della
sequenziale della lista e delle funzioni
cons, car
, canoniche
cdr
e null.
#include<stdio.h>
#define NMAX_LISTA 3 /* Numero massimo degli elementi della lista
*/
/* definizione del tipo lista mediante array */
typedef int tipo_atomi;
typedef struct modello_lista
{
tipo_atomi elementi[NMAX_LISTA];
int primo,lunghezza;
} tipo_lista;
int null(tipo_lista lis)
{
if (lis.lunghezza==0) return(1); else return(0);
}
/* Effettua l'operazione car sulla lista lis. Per la
lista si usa la rappresentazione sequenziale mediante array */
tipo_atomi car(tipo_lista lis)
{
if (null(lis))
{
printf("operazione non eseguibile\n");
return -1;
}
else
return(lis.elementi[lis.primo]);
}
/* Effettua l'operazione cons su una lista rappresentata con array
e È l'elemento da inserire. La lista È ritornata in lis
*/
void cons(tipo_atomi e,tipo_lista *lis)
{
if ((*lis).lunghezza==NMAX_LISTA)
printf("insufficiente dimensione dell'array\n");
else
{
Continua
6
if (null(*lis))
(*lis).primo=0;
else
if ((*lis).primo==0)
(*lis).primo=NMAX_LISTA-1;
else
(*lis).primo=(*lis).primo-1;
(*lis).elementi[(*lis).primo]=e;
(*lis).lunghezza=(*lis).lunghezza+1;
}
}
/* Effettua l'operazione cdr su una lista rappresentata con array.
La lista È ritornata in lis */
void cdr(tipo_lista *lis)
{
if (null(*lis))
printf("operazione non eseguibile\n");
else
{
if ((*lis).lunghezza==1)
(*lis).primo=0;
else
(*lis).primo=((*lis).primo+1) % NMAX_LISTA;
(*lis).lunghezza=(*lis).lunghezza-1;
}
}
main()
{
tipo_lista lis;
lis.lunghezza=0;
/* inserimento elementi nella lista */
cons(10,&lis);
/* lis=(10)
*/
cons(20,&lis);
/* lis=(20,10)
*/
cons(30,&lis);
/* lis=(30,20,10) */
/* eliminazione elemento dalla lista */
printf("%d\n",car(lis)); /* car(lis)=30
cdr(&lis);
/* lis=(20,10)
printf("%d\n",car(lis)); /* car(lis)=20
cdr(&lis);
/* lis=(10)
printf("%d\n",car(lis)); /* car(lis)=10
}
*/
*/
*/
*/
*/
7
Gli operatori & e * in C
L’operatore &, applicato ad una variabile, restituisce il puntatore (l’in
variabile allocata.
Ad esempio, la funzione scanf vista nel primo programma:
scanf(“%d”, &n);
richiede la lettura di un intero nella variabile n; in questo caso è nece
l’indirizzo della locazione di memoria in cui memorizzare l’intero (&n)
L’operatore * , applicato ad una variabile di tipo puntatore, restituisce
Passaggio di parametri “per variabile” in C
I parametri formali di una funzione C possono essere soltanto parametri v
parametri variabile/riferimento. Lo strumento utilizzato in C per ovviare
puntatore. Ogni volta che una variabile deve essere modificata all’intern
passato ad essa il puntatore a tale variabile. La funzione opera sulla va
puntatore. L’unica eccezione a questa regola è rappresentata dagli array
considerato un parametro variabile.
Questa regola di programmazione è evidente nel programma sopra descritto
Nella funzione
car(tipo_lista lis)
la lista è passata per valore infatti questa funzione non modifica la lis
semplicemente il primo valore. In questo caso il parametro formale è una
Le altre funzioni
void cons(tipo_atomi e,tipo_lista *lis)
void cdr(tipo_lista *lis)
invece rispettivamente inseriscono ed eliminano un elemento dalla lista e
modificata. In questo caso il passaggio di parametri deve essere per vari
formale è un puntatore ad una variabile di tipo tipo_lista (tipo_lista *l
Per quanto riguarda, ad esempio, la funzione cdr questa viene chiamata (n
parametro un puntatore alla variabile lis tramite l’operatore &:
cdr(&lis);
All’interno della funzione si accede alla variabile puntata tramite l’ope
es:(*lis).lunghezza=(*lis).lunghezza–1;
8
Rappresentazione collegata con array: La rappresentazione collegata media
nell’associare ad ogni elemento della lista una componente dell’array, co
- il valore del corrispondente elemento della lista;
- il riferimento all’elemento successivo, cioè il valore dell’indice
quale esso è memorizzato.
Gli elementi sono memorizzati in modo qualunque e il loro ordinamento nel
seguendo i riferimenti. L’ultimo elemento della lista ha come riferimento
componenti dell’array in cui non sono memorizzati elementi della lista so
i nuovi elementi. Questi vengono raccolti in modo collegato nello stesso
libera.
La lista libera rappresenta un serbatoio da cui prelevare component
riversare le componenti che non sono più utilizzate per la lista.
Di seguito è mostrata l’implementazione in C del tipo lista secondo la ra
della funzione di inizializzazione della lista
cons,
libera
car
, cdr
e e
delle
null.
funzioni
Nel Main
vengono eseguite alcune chiamate esemplificative a tali funzioni.
#include<stdio.h>
#define NMAX_LISTA 10
/* numero massimo elementi della lista */
/* definizione tipo lista */
typedef int tipo_atomi;
typedef int tipo_riferimento;
typedef struct modello_lista
{
tipo_atomi dato;
tipo_riferimento prox;
};
typedef struct modello_lista tipo_array_lista[NMAX_LISTA];
int null(tipo_riferimento lis)
{
if (lis==NULL) return(1); else return(0);
}
/* Inizializza la lista libera memorizzata in "elementi" il cui
riferimento iniziale È "iniz_ll"; l'inizializzazione viene
effettuata collegando tra loro tutte le componenti dell'array
nell'ordine corrispondente al valore dell'indice */
void inizializza_lista_libera(tipo_riferimento
*iniz_ll,tipo_array_lista elementi)
{
tipo_riferimento i;
for(i=0;i<NMAX_LISTA;i++) elementi[i].prox=i+1;
*iniz_ll=1;
elementi[NMAX_LISTA-1].prox=NULL;
}
Continua
9
/* Effettua l'operazione car sulla lista rappresentata mediante
array */
tipo_atomi car(tipo_array_lista elementi, tipo_riferimento lis)
{
return elementi[lis].dato;
}
/* Effettua l'operazione cons su una lista rappresentata in modo
collegato mediante array; elementi È l'array e lis il riferimento
iniziale; iniz_ll È il riferimento iniziale della lista libera;
l'effetto dell'operazione È quello di modificare l'array in cui È
memorizzata la lista affinchÈ esso rappresenti la lista risultante
*/
void cons(tipo_atomi e, tipo_array_lista elementi,
tipo_riferimento *lis, tipo_riferimento *iniz_ll)
{
tipo_riferimento temp;
if (*iniz_ll==NULL)
printf("dimensione insufficiente dell'array\n");
else
{
/* il nuovo elemento viene memorizzato
prelevando una componente (la prima)
della lista libera */
temp=*iniz_ll;
*iniz_ll=elementi[*iniz_ll].prox;
elementi[temp].dato=e;
elementi[temp].prox=*lis;
*lis=temp;
}
}
/* effettua l'operazione cdr su una lista rappresentata in modo
collegato mediante array; elementi È l'array e lis il
riferimento iniziale; iniz_ll È il riferimento iniziale della
lista libera; l'effetto dell'operazione È quello di modificare
l'array in cui È memorizzata la lista affinchÈ esso rappresenti la
lista risultante */
void cdr(tipo_riferimento *lis, tipo_riferimento *iniz_ll,
tipo_array_lista elementi)
{
int temp;
if (null(*lis))
printf("operazione non applicabile\n");
else
{
Continua
/* si elimina il primo elemento della lista
10
e si rilascia alla lista libera la componente
non pi— utilizzata */
temp=*lis;
*lis=elementi[*lis].prox;
elementi[temp].prox=*iniz_ll;
*iniz_ll=temp;
}
}
main()
{
tipo_riferimento lis=NULL;
tipo_riferimento iniz_ll=NULL;
tipo_array_lista elementi;
/* inizializzazione lista libera */
inizializza_lista_libera(&iniz_ll,elementi);
/* inserimento elementi */
cons(5,elementi,&lis,&iniz_ll);
cons(15,elementi,&lis,&iniz_ll);
cons(25,elementi,&lis,&iniz_ll);
cons(35,elementi,&lis,&iniz_ll);
/* eliminazione elementi */
printf("%d\n",car(elementi,lis));
cdr(&lis,&iniz_ll,elementi);
printf("%d\n",car(elementi,lis));
cdr(&lis,&iniz_ll,elementi);
printf("%d\n",car(elementi,lis));
cdr(&lis,&iniz_ll,elementi);
printf("%d\n",car(elementi,lis));
}
/*
/*
/*
/*
lis=(5)
lis=(5,15)
lis=(5,15,25)
lis=(5,15,25,35)
*/
*/
*/
*/
/* lis=(5,15,25)
*/
/* lis=(5,15)
*/
/* lis=(5)
*/
11
Rappresentazione collegata con puntatori: Il tipo puntatore è un tipo di
rappresentano indirizzi di locazioni di memoria. Mediante l’uso del tipo
(struct) si può realizzare in modo efficace la rappresentazione collegata
corrispondere ad ogni elemento della lista una istanza del tipo struct co
informazione e da un campo puntatore alla istanza struct successiva. Ques
rappresentazione più efficiente perché non è necessario imporre a priori
dimensione della lista. Lo spazio di memoria occupato è infatti proporzio
elementi della lista stessa.
Di seguito sono mostrate due implementazioni della rappresentazione colle
prima rappresenta la traduzione in C dell’implementazione che il libro pr
seconda è una versione, forse più naturale in C, in non
cui sono
le funzioni
void ma cons
restituiscono la lista modificata dall’operazione.
Versione 1: operazioni cons e cdr implementate con funzioni void
#include<stdio.h>
/* definizione del tipo lista */
typedef struct modello_atomo
{
int val;
struct modello_atomo *next;
} tipo_atomo;
typedef tipo_atomo *tipo_lista;
int null(tipo_lista lis)
{
if (lis==NULL) return(1); else return(0);
}
/* Effettua l'operazione car su una lista rappresentata da record
e puntatori. lis È il puntatore al primo elemento della lista
*/
int car(tipo_lista lis)
{
if (null(lis))
{
printf("operazione non eseguibile\n");
return -1;
}
else
return(lis->val);
}
/* Effettua l'operazione cons su una lista rappresentata da record
e puntatori. val È l'elemento da inserire nella
Continua
lista. La lista È restituita in lis */
12
void cons(int val,tipo_lista *lis)
{
tipo_lista temp;
temp=(tipo_lista)malloc(sizeof(tipo_atomo));
temp->val=val;
temp->next=*lis;
*lis=temp;
}
/* Effettua l'operazione cdr su una lista rappresentata da record
e puntatori. La lista È restituita in lis. */
void cdr(tipo_lista *lis)
{
tipo_lista temp;
if (null(*lis))
printf("operazione non eseguibile");
else
{
temp=*lis;
*lis=(*lis)->next;
free(temp);
}
}
main()
{
tipo_lista app,l;
l=NULL;
/* Inserimento elementi nella lista */
cons(10,&l);
/* l=(10)
*/
cons(20,&l);
/* l=(20,10)
*/
cons(30,&l);
/* l=(30,20,10) */
/* display degli elementi della lista */
app=l;
while(app != NULL) {
printf("%d\n",app->val);
app=app->next;
}
/* eliminazione degli elementi dalla
printf("%d\n",car(l)); /* car(l)=30
cdr(&l);
/* l=(20,10)
printf("%d\n",car(l)); /* car(l)=20
cdr(&l);
/* l=(10)
printf("%d\n",car(l)); /* car(l)=10
}
lista */
*/
*/
*/
*/
*/
13
Versione 2: operazioni cons e cdr implementate con funzioni che
restituiscono la lista modificata
#include<stdio.h>
/* Definizione del tipo lista */
typedef struct modello_atomo
{
int val;
struct modello_atomo *next;
} tipo_atomo;
typedef tipo_atomo *tipo_lista;
int null(tipo_lista lis)
{
if (lis==NULL) return(1); else return(0);
}
/* Effettua l'operazione car su una lista rappresentata da
record e puntatori. lis È il puntatore al primo elemento
della lista */
int car(tipo_lista lis)
{
if (null(lis))
{
printf("operazione non eseguibile\n");
return -1;
}
else
return(lis->val);
}
/* Effettua l'operazione cons su una lista rappresentata da
record e puntatori. lis È il puntatore al primo elemento
della lista */
tipo_lista cons(int val,tipo_lista lis)
{
tipo_lista temp;
temp=(tipo_lista)malloc(sizeof(tipo_atomo));
temp->val=val;
temp->next=lis;
lis=temp;
return lis;
}
Continua
14
/* Effettua l'operazione cdr su una lista rappresentata da
record e puntatori. lis È il puntatore al primo elemento
della lista */
tipo_lista cdr(tipo_lista lis)
{
tipo_lista temp;
if (null(lis))
printf("operazione non eseguibile");
else
{
temp=lis;
lis=lis->next;
free(temp);
}
return lis;
}
main()
{
tipo_lista app,l;
l=NULL;
/* inserimento elementi nella lista */
l=cons(10,l);
/* l=(10)
*/
l=cons(20,l);
/* l=(20,10)
*/
l=cons(30,l);
/* l=(30,20,10) */
/* display degli elementi inseriti */
app=l;
while(app != NULL) {
printf("%d\n",app->val);
app=app->next;
}
/* eliminazione degli elementi dalla lista */
printf("%d\n",car(l));
/* car(l)=30 */
l=cdr(l);
/* l=(20,10) */
printf("%d\n",car(l));
/* car(l)=20 */
l=cdr(l);
/* l=(10)
*/
printf("%d\n",car(l));
/* car(l)=10 */
}
15
Puntatori: C e Pascal
Le operazioni usualmente disponibili su una variabile p di tipo punta
1. l’accesso alla locazione il cui indirizzo è memorizzato in p.
es:
*p in C
p^ in Pascal
2. la richiesta di una nuova locazione di memoria.
es:
new(p); in Pascal
p=(tipo_lista)malloc(sizeof(tipo_atomo)); in C
la funzione malloc ha la stesso scopo della funzione new, è necessar
dimensione della porzione di memoria che si intende allocare. Nell’e
sizeof, applicato all’identificatore di tipo tipo_atomo, restituisce
byte occupati da una istanza della struttura tipo_atomo.
La funzione malloc restituisce un puntatore di tipo indefinito; per
effettuare una conversione di tipo (casting). Questo si ottiene inse
chiamata alla malloc l’espressione (<tipo>). Nel nostro caso p=(tipo
3. il rilascio della locazione di memoria il cui indirizzo è memorizzat
es:
dispose(p); in Pascal
free(p); in C
Per la gestione delle variabili puntatore in C oltre agli operatori
usare anche l’operatore
. Se p è un puntatore (*p).val=p
val.
Un'altra differenza è il nome della costante che rappresenta il puntam
nil mentre in C è NULL.
16
Pile
Rappresentazione sequenziale: Una pila è un tipo astratto che consente di
multiinsieme di elementi gestito con disciplina LIFO (“Last In First Out”
sequenziale si utilizza una variabile
elementi
di
).tipo
Se Narray
è la (
dimensione dell’array
l’elemento affiorante è memorizzato in posizione N-1, il penultimo in pos
al primo elemento inserito, che è memorizzato in posizione 0. In un’ulter
(posizione_top
) si memorizza l’indice dell’elemento affiorante.
Di seguito è mostrata l’implementazione in C del tipo pila secondo la rap
delle funzioni
push, pop e test_pila_vuota. Nel Main vengono eseguite alcune c
esemplificative a tali funzioni.
#include<stdio.h>
#define NMAX_ARRAY_PILA 10
pila */
#define PILA_VUOTA -1
/* numero massimo degli elementi della
/* definizione tipo pila */
typedef int tipo_elementi;
typedef struct modello_pila
{
tipo_elementi elementi[NMAX_ARRAY_PILA];
int posizione_top;
} tipo_pila;
void assegna_vuota(tipo_pila *p)
{
(*p).posizione_top=PILA_VUOTA;
}
int test_pila_vuota(tipo_pila p)
{
if (p.posizione_top==NMAX_ARRAY_PILA-1) return -1; else return 0;
}
/* effettua l'operazione push sulla pila p rappresentata mediante
array.
e È l'elemento da inserire nella pila */
void push(tipo_pila *p,tipo_elementi e)
{
if (test_pila_vuota(*p))
printf("insufficiente dimensione dell'array\n");
else
{
(*p).posizione_top=(*p).posizione_top+1;
(*p).elementi[(*p).posizione_top]=e;
}
Continua
17
}
/* effettua l'operazione pop sulla pila rappresentata mediante
array.
p È la pila */
void pop(tipo_pila *p)
{
if ((*p).posizione_top==PILA_VUOTA)
printf("operazione non applicabile");
else
(*p).posizione_top=(*p).posizione_top-1;
}
main()
{
tipo_pila p;
/* assegnazione pila vuota alla pila */
assegna_vuota(&p);
/* inserimento valori */
push(&p,5);
push(&p,35);
push(&p,45);
push(&p,57);
/* eliminazione valori */
pop(&p);
/* elimina 57 */
pop(&p);
/* elimina 45 */
pop(&p);
/* elimina 35 */
pop(&p);
/* elimina 5 */
pop(&p);
/* operazione non applicabile */
}
18
Rappresentazione collegata con La
puntatori:
rappresentazione collegata della pila p
implementata con puntatori e strutture. Un modo semplice di realizzare la
struttura collegata con puntatori è quello di effettuare l’inserimento e
testa alla lista. In questo modo, il puntatore iniziale della lista punte
affiorante, se la pila non è vuota; in caso contrario, il suo valore sarà
Di seguito è mostrata l’implementazione in C del tipo pila secondo la rap
delle funzioni
push, pop e test_pila_vuota. Nel Main vengono eseguite alcune c
esemplificative a tali funzioni.
#include<stdio.h>
/* definizione del tipo pila */
typedef int tipo_elementi;
typedef struct modello_record
{
tipo_elementi elemento;
struct modello_record *next;
} record_pila;
typedef record_pila *punt_pila;
void assegna_vuota(punt_pila *p)
{
(*p)=NULL;
}
int test_pila_vuota(punt_pila p)
{
if (p==NULL) return 1; else return 0;
}
/* effettua l'operazione pop su una pila rappresentata mediante
record e puntatori. p È il puntatore alla pila */
void pop(punt_pila *p)
{
punt_pila q;
if (test_pila_vuota(*p))
printf("operazione non applicabile\n");
else
{
q=(*p);
(*p)=(*p)->next;
free(q);
}
}
/* effettua l'operazione di push su una pila
rappresentata mediante
Continua
19
record e puntatori. p È il puntatore alla pila e È l'elemento
da inserire */
void push(punt_pila *p,tipo_elementi e)
{
punt_pila temp;
temp=(punt_pila)malloc(sizeof(record_pila));
temp->elemento=e;
temp->next=(*p);
(*p)=temp;
}
main()
{
punt_pila p;
/* assegna alla pila la pila vuota */
assegna_vuota(&p);
/* inserimento valori */
push(&p,5);
push(&p,35);
push(&p,45);
push(&p,57);
/* eliminazione valori */
pop(&p);
/* elimina 57 */
pop(&p);
/* elimina 45 */
pop(&p);
/* elimina 35 */
pop(&p);
/* elimina 5 */
pop(&p);
/* operazione non applicabile */
}
20
Code
Rappresentazione collegata con Una
puntatori:
coda è un tipo astratto che consente d
rappresentare un multiinsieme di elementi gestito con disciplina FIFO (“F
Nella rappresentazione collegata con puntatori si fa generalmente uso di
puntatore. La prima
primo)( contiene il puntatore all’elemento in testa alla cod
(ultimo) contiene il puntatore all’elemento che si trova alla fine della
vuota sarà indicata dal valore NULL per entrambe queste variabili.
Di seguito è mostrata l’implementazione in C del tipo coda secondo la rap
delle funzioni
in_coda
, out_coda
, test_coda_vuota. Nel Main vengono eseguite alcune
esemplificative a tali funzioni.
#include<stdio.h>
/* definizione tipo dato coda */
typedef int tipo_elementi;
typedef struct modello_record
{
tipo_elementi elemento;
struct modello_record *next;
} record_coda;
typedef record_coda *punt_coda;
int test_coda_vuota(punt_coda p)
{
if (p==NULL) return -1; else return 0;
}
/* Inserisce l'elemento e in una coda; la coda È rappresentata
mediante
record e puntatori; p È il puntatore al primo elemento della
coda,
u all'ultimo */
void in_coda(punt_coda *p,punt_coda *u,tipo_elementi e)
{
if (test_coda_vuota(*p))
{
*p=(punt_coda)malloc(sizeof(record_coda));
*u=*p;
}
else
{
(*u)->next=(punt_coda)malloc(sizeof(record_coda));
*u=(*u)->next;
}
(*u)->elemento=e;
(*u)->next=NULL;
Continua
21
}
/* Elimina un elemento dalla coda; la coda È rappresentata
mediante
record e puntatori; p È il puntatore al primo elemento della
coda, u
all'ultimo */
void out_coda(punt_coda *p,punt_coda *u)
{
punt_coda aux;
if (test_coda_vuota(*p))
printf("coda vuota: operazione non applicabile\n");
else
{
aux=*p;
(*p)=(*p)->next;
if (*p==NULL) *u=NULL;
free(aux);
}
}
main()
{
punt_coda p,u;
p=NULL;
u=NULL;
/* inserimento elementi in coda */
in_coda(&p,&u,5);
/* coda=(5)
in_coda(&p,&u,24);
/* coda=(5,24)
in_coda(&p,&u,35);
/* coda=(5,24,35)
in_coda(&p,&u,53);
/* coda=(5,24,35,53)
*/
*/
*/
*/
/* eliminazione elementi in coda */
out_coda(&p,&u);
/* coda=(24,35,53)
*/
out_coda(&p,&u);
/* coda=(35,53)
*/
out_coda(&p,&u);
/* coda=(53)
*/
out_coda(&p,&u);
/* coda=()
*/
out_coda(&p,&u);
/* operazione non applicabile */
}
22
Alberi binari
Rappresentazione collegata con Gli
puntatori:
alberi binari sono alberi in cui ogni
massimo due figli. Sui figli di ogni nodo è definito un ordinamento: in g
prima nell’ordinamento è detto figlio sinistro, mentre l’altro è detto fi
rappresentazione collegata con puntatori il tipo struct che si utilizza p
nodo viene definito con tre campi: uno per l’informazione associata al no
sottoalbero sinistro ed uno per il puntatore al sottoalbero destro. Il va
puntatore indica che il corrispondente sottoalbero è vuoto. Di seguito è
in C del tipo albero binario secondo la rappresentazione descritta, dell
test_albero_vuoto
e costruisci. Quest’ultima funzione costruisce un albero bin
albero in notazione parentetica inserito in input. Vengono implementate a
visita in preordine dell’albero. La prima versione è ricorsiva la seconda
struttura dati pila. Nel Main vengono eseguite alcune chiamate esemplific
#include<stdio.h>
typedef struct modello_nodo
{
int info;
struct modello_nodo *sin;
struct modello_nodo *des;
} tipo_nodo;
typedef tipo_nodo *punt_albero;
int test_albero_vuoto(punt_albero alb)
{
if (alb==NULL) return 1; else return 0;
}
/* Realizza l'operazione sinistro su un albero binario
rappresentato
mediante record e puntatori; alb È il puntatore iniziale
dell'albero */
punt_albero *sinistro(punt_albero alb)
{
if (test_albero_vuoto(alb))
{
printf("operazione non applicabile\n");
return NULL;
}
else
{
return &(alb->sin);
}
}
Continua
23
/* Realizza l'operazione destro su un albero binario rappresentato
mediante record e puntatori; alb È il puntatore iniziale
dell'albero. */
punt_albero *destro(punt_albero alb)
{
if (test_albero_vuoto(alb))
{
printf("operazione non applicabile\n");
return NULL;
}
else
{
return &(alb->des);
}
}
/* Costruisce la rappresentazione con puntatori e record
di un albero binario di cui si legge da ingresso
la rappresentazione parenteticail puntatore alla radice dell'albero costruito viene restituito
con la variabile alb. */
void costruisci(punt_albero *alb)
{
char ch;
scanf("%c",&ch);
scanf("%c",&ch);
if (ch==')') /* l'albero da costruire È vuoto */
*alb=NULL;
else
{
/* si crea il nodo corrispondente alla radice */
*alb=(punt_albero)malloc(sizeof(tipo_nodo));
(*alb)->info=ch;
/* si costruisce il sottoalbero sinistro */
costruisci(sinistro(*alb));
/* si costruisce il sottoalbero destro */
costruisci(destro(*alb));
scanf("%c",&ch);
}
}
/* Funzione ricorsiva che effettua la visita in preordine di un
albero binario per stampare i valori dei nodi;
alb È la radice dell'albero binario. */
Continua
24
void preordine(punt_albero alb)
{
if (alb!=NULL)
{
/* analizza la radice */
printf("%c\n",(*alb).info);
/* analizza il sottoalbero sinistro */
preordine(alb->sin);
/* analizza il sottoalbero destro */
preordine(alb->des);
}
}
/* Definizione del tipo di dato pila e delle relative funzioni
di gestione. Necessari per la versione iterativa della visita
in preordine dell'albero binario. */
typedef punt_albero tipo_elementi;
typedef struct modello_record
{
tipo_elementi elemento;
struct modello_record *next;
} record_pila;
typedef record_pila *punt_pila;
void assegna_vuota(punt_pila *p)
{
(*p)=NULL;
}
int test_pila_vuota(punt_pila p)
{
if (p==NULL) return 1; else return 0;
}
void pop(punt_pila *p, punt_albero *alb)
{
punt_pila q;
if (test_pila_vuota(*p))
printf("operazione non applicabile\n");
else
{
q=(*p);
(*alb)=(*p)->elemento;
(*p)=(*p)->next;
free(q);
}
}
Continua
25
void push(punt_pila *p,tipo_elementi e)
{
punt_pila temp;
temp=(punt_pila)malloc(sizeof(record_pila));
temp->elemento=e;
temp->next=(*p);
(*p)=temp;
}
/* Funzione iterativa che effettua la visita in preordine di un
albero binario per stampare i valori dei nodi; alb È la radice
dell'albero binario. */
void preordine2(punt_albero *alb)
{
/* Assegna a pila il valore pari a pila vuota */
punt_pila pila;
assegna_vuota(&pila);
/* Se l'albero non È vuoto, memorizza nella pila il puntatore alla
radice, in modo che essa sia il primo nodo ad essere visitato
*/
if (*alb!=NULL) push(&pila,*alb);
while (!test_pila_vuota(pila))
{
/* L'elemento affiorante della pila È il puntatore alla radice
del
prossimo sottoalbero da visitare, cioÈ È il puntatore al
prossimo
nodo dell'albero da visitare */
pop(&pila,alb);
printf("%c\n",(*alb)->info);
/* Si inseriscono nella pila i puntatori al figlio destro
(prima) e
al figlio sinistro (dopo), solo se sono diversi da NULL;
l'ordine
È dovuto al fatto che il figlio sinistro È il prossimo da
analizzare , e quindi deve essere l'ultimo ad essere inserito
nella pila */
if ((*alb)->des!=NULL) push(&pila,(*alb)->des);
if ((*alb)->sin!=NULL) push(&pila,(*alb)->sin);
}
}
main()
{
punt_albero a;
Continua
26
a=NULL;
/* costruzione dell'albero */
costruisci(&a);
/* display dei nodi: visita preordine ricorsiva */
preordine(a);
/* display dei nodi: visita preordine iterativa */
preordine2(&a);
}
Correttezza
Triangolo errato:
Programma errato per il problema del tipo di triangolo.
#include<stdio.h>
main()
{
int primo,secondo,terzo;
int uguali;
scanf("%d %d %d",&primo,&secondo,&terzo);
uguali=0;
if (primo==secondo) uguali=uguali+1;
if (primo==terzo) uguali=uguali+2;
if (secondo==terzo) uguali=uguali+1;
if (uguali==0) printf("scaleno\n");
if (uguali==1) printf("isoscele\n");
else
printf("equilatero\n");
}
27
Ricerca binaria:
La ricerca binaria è un metodo di ricerca di un valore in u
valori che ha una complessità pari a log N (la base del logaritmo è 2). S
cui fare la ricerca siano disposti in un array di dimensione N. L’idea ch
binaria è la seguente: si accede all’elemento mediano (indice=N/2) dell’a
valore che si sta cercando. Se l’elemento è quello cercato allora la rice
Se l’elemento mediano ha una chiave maggiore di quello che si sta cercand
prosegue con lo stesso metodo nella parte dell’array con indice inferiore
mediano. Viceversa, se l’elemento mediano ha una chiave inferiore la rice
dell’array con indice superiore a quello dell’elemento mediano.
Di seguito l’implementazione in C di una funzione di ricerca binaria.
#include<stdio.h>
/* la funzione prende come parametro un valore
intero val, un array di elementi ordinati e il numero
degli elementi dell'array e restituisce
1 se val È contenuto nel vettore 0 altrimenti.
Viene utilizzato un algoritmo di ricerca binaria */
int ric_bin(int val,int vet[],int n)
{
int inf,sup,med,trovato;
inf=1;
sup=n;
trovato=0;
while (sup-inf>=0 && !trovato)
{
med=(inf+sup)/2;
if (vet[med]==val) trovato=1;
if (vet[med]<val) inf=med+1;
if (vet[med]>val) sup=med-1;
}
return trovato;
}
main()
{
/* valorizzazione array */
int vet[10]={2,2,3,4,5,8,9,45,67,99};
/* ricerca binaria su array */
if (ric_bin(14,vet,10)) printf("elemento trovato");
}
28
Complessità
Polinomio quadratico e lineare
Programma
: per la valutazione di un polinomio di g
punto. Vengono implementate due funzioni: la prima è quadratica (compless
è lineare (complessità O(n)).
#include<stdio.h>
#define N 4
/* N È il grado del polinomio */
/* Effettua il calcolo del polinomio di grado N di cui
gli N+1 coefficienti sono memorizzati nell'array a.
L'ascissa su cui eseguire il calcolo viene letto da
input.
L'algoritmo usato È quadratico. */
float pol_1(int a[])
{
int i,j;
float x,y,val;
/* x contiene il valore del punto in cui si vuole valutare il
polinomio,
y il valore di una potenza di x, val il valore del polinomio
nel punto
x */
val=a[0];
scanf("%f",&x);
for(i=1;i<=N;i++)
{
y=1;
for(j=1;j<=i;j++) y=y*x;
val=val+(a[i]*y);
}
return val;
}
/* Effettua il calcolo del polinomio di grado N di cui
gli N+1 coefficienti sono memorizzati nell'array a.
L'ascissa su cui eseguire il calcolo viene letto da
input.
L'algoritmo usato È lineare. */
float pol_2(int a[])
{
int i,j;
float x,y,val;
/* x contiene il valore del punto in cui si vuole valutare il
polinomio,
y il valore di una potenza di x, val il valore del polinomio
nel punto x */
Continua
val=a[0];
29
scanf("%f",&x);
y=1;
for(i=1;i<=N;i++)
{
y=y*x;
val=val+(a[i]*y);
}
return val;
}
main()
{
/* definizione coefficienti */
int vet[N+1]={2,3,46,6,3};
/* display risultati */
printf("programma quadratico: %f\n",pol_1(vet));
printf("programma lineare: %f\n",pol_2(vet));
}
30
Ordinamento
Selection Sort:
L’algoritmo di ordinamento per selezione esegue N iterazioni
dell’array). Nell’iterazione i-esima si scandiscono gli elementi dell’arr
seleziona l’elemento minimo e si scambia con l’elemento i-esimo. Di segui
#include<stdio.h>
#define N 5
/* N È la dimensione massima dell'array */
/* definizione del tipo elemento dell'array */
typedef char tipo_informazione;
typedef struct modello_elem
{
tipo_informazione inf;
int chiave;
} elem;
void scambia(elem *a,elem *b)
{
elem app;
app=*b;
*b=*a;
*a=app;
}
/* Effettua l'ordinamento selection sort sull'array z di n
elementi */
void ordinamento_per_selezione(elem z[],int n)
{
int i,j,imin;
for(i=0;i<=n-1;i++)
{
/* ricerca della componente minima tra z[i] e z[n] */
imin=i;
for(j=i+1;j<=n;j++)
if (z[j].chiave<z[imin].chiave) imin=j;
/* scambia z[imin] e z[i] */
scambia(&z[i],&z[imin]);
}
}
main()
{
int k=0;
elem vet[N];
/* riempimento array */
Continua
31
vet[0].chiave=2;
vet[1].chiave=45;
vet[2].chiave=8;
vet[3].chiave=99;
vet[4].chiave=67;
vet[0].inf='a';
vet[1].inf='c';
vet[2].inf='b';
vet[3].inf='e';
vet[4].inf='d';
/* ordinamento array */
ordinamento_per_selezione(vet,N-1);
/* array risultato */
for(k=0;k<N;k++) printf("%c\n",vet[k].inf);
}
Bubble Sort:
L’ordinamento a bolle si basa sul principio che in un array ord
due elementi adiacenti z[i] e z[i+1] abbiamo che il primo è minore o ugua
confronta ripetutamente coppie adiacenti che vengono scambiate se non ri
Se k è l’indice dell’ultimo elemento dell’array, la prima iterazione conf
z[k].chiave < z[k-1].chiave allora scambia z[k] e z[k-1]. All’iterazione
confronto viene fatto tra z[k-1].chiave e z[k-2].chiave e così via fino a
z[0].chiave. Alla fine della prima scansione dell’array in z[0] c’è l’ele
occupa quindi la sua posizione definitiva. Non è necessario nelle scansio
a z[0] ma basta fermarsi a z[1]. Generalizzando si può dire che la scansi
dall’elemento dell’array in posizione k ed arriva all’elemento in posizio
scansione dell’array non viene effettuato nemmeno uno scambio significa c
e che è inutile proseguire con le scansioni successive. Di seguito l’impl
#include<stdio.h>
#define N 5
/* N È il numero degli elementi dell'array da
ordinare */
/* Definizione del elemento dell'array. L'ordinamento verrà
eseguito
rispetto al campo chiave. */
typedef char tipo_informazione;
typedef struct modello_elem
{
tipo_informazione inf;
int chiave;
} elem;
void scambia(elem *a,elem *b)
{
elem app;
app=*b;
*b=*a;
*a=app;
}
/* Funzione di ordinamento a bolle (Bubble Sort).
Continua
32
vet È un array di elementi, n gli elementi dell'array. */
void ordinamento_a_bolle(elem vet[], int n)
{
int fine,i,j;
fine=0;
i=0;
while (!fine && i<n)
{
fine=1;
i++;
for(j=n-1;j>i;j--)
{
if (vet[j].chiave<vet[j-1].chiave)
{
/* scambio valori vet[j] e vet[j-1] */
scambia(&vet[j],&vet[j-1]);
/* aggiornamento variabile fine */
fine=0;
}
}
}
}
main()
{
int k=0;
elem vet[N];
/* riempimento array */
vet[0].chiave=2;
vet[0].inf='a';
vet[1].chiave=45; vet[1].inf='c';
vet[2].chiave=8;
vet[2].inf='b';
vet[3].chiave=99; vet[3].inf='e';
vet[4].chiave=67; vet[4].inf='d';
/* ordinamento array */
ordinamento_a_bolle(vet,N);
/* display array ordinato */
for(k=0;k<N;k++) printf("%c\n",vet[k].inf);
}
33
Mergesort: Algoritmo di fusione
L’algoritmo Mergesort si basa sull’operazione di fusione di due array or
interi x e y ordinati in ordine crescente, con m componenti ciascuno, si
array z ordinato costituito dai 2m elementi degli array x e y. Per fare c
la scansione degli array x e y ed un indice k per l’inserimento nell’arra
i=0, j=0, k=0 ad ogni iterazione si confrontano x[i] e y[j]. I casi possi
x[i]<=y[j]: si pone z[k]=x[i], si incrementano i e k
x[i]>y[j]: si pone z[k]=y[j], si incrementano j e k
Quando si completa la scansione di uno dei due array x o y si pongono in
dell’altro array. Di seguito è mostrata l’implementazione in C dell’algor
#include<stdio.h>
#define N 5 /* N È il numero di elementi degli array */
/* Funzione per la fusione (merge) di due array.
Gli array x e y hanno N componenti ciascuno,
z È l'array risultato,
dim È la dimensione dell'array risultato */
void fusione(int x[],int y[],int z[],int *dim)
{
int i,j,k;
/* la variabile i serve per scorrere l'array x, la variabile j
l'array y
e la variabile k l'array z */
i=0;j=0;k=0;
while (i<=N-1 && j<=N-1)
{
if (x[i]<=y[j])
{
z[k]=x[i];i=i+1;
}
else
{
z[k]=y[j];j=j+1;
}
k=k+1;
}
/* a questo punto È stata completata la scansione di almeno
uno dei due array */
if (i<=N-1)
do /* si completa z con elementi da x */
{
z[k]=x[i];i=i+1;k=k+1;
}
while (i<=N-1);
else
Continua
34
do
{
z[k]=y[j];j=j+1;k=k+1;
}
while (j<=N-1);
*dim=k;
}
main()
{
int k=0;
int dim_fusione=0;
/* riempimento array */
int vet1[N]={2,3,9,18,20};
int vet2[N]={4,7,67,88,89};
int vet_fusione[2*N];
/* merge dei due array in vet_fusione */
fusione(vet1,vet2,vet_fusione,&dim_fusione);
/* display dell'array risultato */
for(k=0;k<=dim_fusione-1;k++) printf("%d\n",vet_fusione[k]);
}
Mergesort: Algoritmo Mergesort
L’algoritmo è intrinsecamente ricorsivo e può essere così descritto: se l
un confronto ed eventualmente uno scambio, si ottiene l’array ordinato. S
elementi lo si divide in due array aventi ciascuno la metà degli elementi
usando lo stesso metodo, e, quindi , si realizza la fusione dei due array
ordinato. La funzione di fusione utilizzata dal programma di mergesort è
quella descritta sopra. In questo caso infatti la funzione di fusione ope
come parametri di ingresso tre indici inf, med e sup. Si ha che:
- le chiavi comprese tra inf e med sono ordinate
- le chiavi comprese tra med+1 e sup sono ordinate
- dopo l’esecuzione della funzione fusione le chiavi tra inf e sup dev
Di seguito è mostrata l’implementazione in C dell’algoritmo di Mergesort
modificata.
#include<stdio.h>
#define N 5
/* dimensione dell'array */
/* definizione elementi array */
typedef char tipo_informazione;
typedef struct modello_elem
{
tipo_informazione inf;
int chiave;
} elem;
Continua
35
void scambia(elem *a,elem *b)
{
elem app;
app=*b;
*b=*a;
*a=app;
}
/* esegue la fusione dei due sotto array
1) da vet[i] a vet[k] estremi inclusi
2) da vet[k+1] a vet[j] estremi inclusi
il risultato È il sottoarray che v… da vet[i] a vet[j] estremi
inclusi */
void merge(int i,int k,int j,elem vet[])
{
elem vres[N];
int x=0;
int p1=i;
int p2=k+1;
int pres=0;
while (p1<=k && p2<=j)
{
if (vet[p1].chiave<=vet[p2].chiave)
{
vres[pres]=vet[p1];
p1=p1+1;
}
else
{
vres[pres]=vet[p2];
p2=p2+1;
}
pres=pres+1;
}
if (p1<=k)
do
{
vres[pres]=vet[p1];
p1=p1+1;
pres=pres+1;
}
while(p1<=k);
else
do
{
vres[pres]=vet[p2];
p2=p2+1;
pres=pres+1;
Continua
36
}
while(p2<=j);
for(x=0;x<=j-i;x++)
{
vet[x+i]=vres[x];
}
}
/* esegue l'ordinamento mergesort sul vettore z
limitatamente al sottoarray che v… da z[i] a z[j] estremi
inclusi.
n È la dimensione dell'array */
void msort(int i,int j,elem z[],int n)
{
int k,app;
if (i+1==j)
if (z[i].chiave>z[j].chiave) scambia(&z[i],&z[j]);
if (i+1<j)
{
k=(i+j)/2;
msort(i,k,z,n);
msort(k+1,j,z,n);
merge(i,k,j,z);
}
}
main()
{
int k=0;
elem vet[N];
/* riempimento array */
vet[0].chiave=2;
vet[0].inf='a';
vet[1].chiave=45; vet[1].inf='c';
vet[2].chiave=8;
vet[2].inf='b';
vet[3].chiave=99; vet[3].inf='e';
vet[4].chiave=67; vet[4].inf='d';
/* ordinamento array */
msort(0,N-1,vet,N);
/* display array risultato */
for(k=0;k<N;k++) printf("%c\n",vet[k].inf);
}
37
Riferimenti
1. “Fondamenti di programmazione dei calcolatori elettronici”:
C.Batini, L.Carlucci Aiello, M.Lenzerini, A.Marchetti Spaccamela, A
Franco Angeli
2. “Dal linguaggio Pascal al linguaggio C”
G.Di Battista, F.Vargiu
Masson
38