Sei sulla pagina 1di 5

Università degli Studi di Firenze, Scuola di Ingegneria

Corso di Laurea in Ingegneria Informatica – Prof. Stefano Berretti

Fondamenti di Informatica
PROVA SCRITTA – 23 Gennaio 2014

Esercizio 1. (6 punti)
Scrivere l'albero sintattico e verificare la legalità della seguente istruzione C:

result += (a.V[i++] > *(ptr->V + i)) * 0.7;

nell'ambito delle seguenti dichiarazioni, definizioni e istruzioni:

struct list {
float V[10];
int code;
struct list * next;
};

struct list a, *ptr;


int i, result = 0;
ptr = (struct list *) malloc( sizeof(struct list) );
for ( i=0; i<10; i++ ) {
a.V[i] = i+1;
ptr->V[i] = 0.5;
}

Si discuta inoltre la semantica dell'istruzione indicando i side effects associati alla sua esecuzione nel caso i=2.

Esercizio 2. (6 punti)
Scrivere la funzione C che realizza l'inserimento ordinato in una lista collegata con array ed indici. Ipotizzare che i valori
della lista siano interi.

Esercizio 3. (8 punti)
Scrivere le funzioni C che realizzano l'algoritmo di ordinamento quicksort. Scrivere anche l'equazione di costo
dell'algoritmo discutendo la complessità nei vari casi.

Esercizio 4. (10 punti)


Scrivere la funzione C che riceve in ingresso due liste collegate con puntatori ( lista1 e lista2 nel seguito) di valori
interi ordinati in senso crescente ed opera nel modo seguente:
– scandisce la lista1 e la completa con gli elementi della lista2 il cui valore è compreso tra due valori
consecutivi della lista1;
– valori della lista2 uguali a quelli della lista1 non sono copiati;
– la funzione deve gestire anche i casi di inserimento di elementi della lista2 in testa/coda della lista1;
– la funzione deve restituire il numero di elementi della lista2 inseriti nella lista1.
Tutte le operazioni precedenti devono essere realizzate senza allocare/deallocare memoria. Scrivere anche l'equazione
di costo della funzione.

Esempio:
lista1 3 5 7 8 10 11 12
lista2 1 2 4 5 6 7 10 13 14
lista1 al termine della esecuzione 1 2 3 4 5 6 7 8 10 11 12 13 14
lista2 al termine della esecuzione 5 7 10
Università degli Studi di Firenze, Scuola di Ingegneria
Corso di Laurea in Ingegneria Informatica – Prof. Stefano Berretti

Fondamenti di Informatica
PROVA SCRITTA – 23 Gennaio 2014

Exercise 1. (6 points)
Write the syntactic tree that verifies the legality of the following C instruction:

result += (a.V[i++] > *(ptr->V + i)) * 0.7;

considering the following declarations, definitions and instructions:

struct list {
float V[10];
int code;
struct list * next;
};

struct list a, *ptr;


int i, result = 0;
ptr = (struct list *) malloc( sizeof(struct list) );
for ( i=0; i<10; i++ ) {
a.V[i] = i+1;
ptr->V[i] = 0.5;
}

It is also required to discuss the semantic of the above instruction indicating the side effects that are associated to its
execution for i=2.

Exercise 2. (6 points)
Write the C function that realizes the algorithm for ordered insert in a linked list with array and indices. It is supposed
that the values of the list are integers.

Exercise 3. (8 points)
Write the C functions that realizes the quicksort algorithm. It is also required to write the cost equation of the
algorithm discussing the related complexity in the various cases.

Exercise 4. (10 points)


Write the C function that receives as input two linked lists with pointers (list1 and list2 in the following) of
integer values sorted in ascending order and operates in the following way:
– iterates on list1 and completes it with the elements of list2 whose value is in between two consecutive
values of list1;
– values of list2 that are equal to those of list1 are never copied from list2 to list1;
– the function must consider also the cases in which the elements of list2 have to be inserted in the
head/tail of list1;
– the function must return the number of elements of list2 that have been inserted in list1.
All the above operations of the function must be performed without any memory allocation/deallocation. It is also
required to write the cost equation of the function and its complexity.

Example:
list1 3 5 7 8 10 11 12
list2 1 2 4 5 6 7 10 13 14
list1 after execution 1 2 3 4 5 6 7 8 10 11 12 13 14
list2 after execution 5 7 10
Soluzione

Esercizio 1.

result += (a.V[i++] > *(ptr->V + i)) * 0.7;

Sequenza delle riduzioni (in forma compatta):

<identifier> += (<identifier>.<identifier>[<identifier>++] > *(<identifier>->


<identifier>+<identifier>)) * <const>;
<var> += (<var>.<identifier>[<var>++] > *(<expr>->
<identifier>+<var>)) * <expr>;
<var> += (<var>[<var>++] > *(<var>+<var>)) * <expr>;
<var> += (<expr>[<expr>] > *(<expr><op2><expr>)) * <expr>;
<var> += (<var> > *(<expr>)) * <expr>;
<var> += (<expr> > *<expr>) * <expr>;
<var> += (<expr> > <var>) * <expr>;
<var> += (<expr><op2><expr>) * <expr>;
<var> += (<expr>) * <expr>;
<var> += <expr><op2><expr>;
<var> <op2>= <expr>
<expr>;
<statement>

I side effects associati all'esecuzione dell'istruzione per i=2 sono:


result += (a.V[i++] > *(ptr->V + i)) * 0.7;
result = result + (a.V[2] > *(ptr->V+2)) * 0.7;
result = 0 + (3.0 > 0.5) * 0.7;
result = 0 + 1 * 0.7;
result = 0 + 0.7;
result = 0.7;
result = 0;

assegna il valore intero 0 alla variabile result. L'altro side effect è l'incremento postfisso dell'indice i : i = 3

Esercizio 2.

typedef unsigned short int boolean;


#define TRUE 1
#define FALSE 0

boolan ord_insert(struct list * ptr, int value )


{
int moved;
int * pos_ptr;

if( ptr->free != ptr->size ) {


moved = ptr->free;
ptr->free = ptr->buffer[moved].next;
pos_ptr = &(ptr->first);
while( *pos_ptr != ptr->size && ptr->buffer[*pos_ptr].value < value) {
pos_ptr = &(ptr->buffer[*pos_ptr].next);
}
ptr->buffer[moved].value = value;
ptr->buffer[moved].next = *pos_ptr;
*pos_ptr = moved;

return TRUE;
}
else
return FALSE
}

Esercizio 3.

void quicksort_r( int * V, int N )


{
int q;

if ( N > 1 ) {
q = partition( V, N );
quicksort_r( V, q );
quicksort_r( &V[q], N-q-1 );
}
}

int partition( int * V, int N )


{
int l, r, pivot;

pivot = V[0];
l = 0;
r = N;
while ( l < r ) {
do {
r--;
} while ( V[r] > pivot && r > l );
if ( r != l ) {
do {
l++;
} while ( V[l] <= pivot && l < r );
swap(V, l, r);
}
}
swap(V, l, 0);
return l;
}

void swap( int * V, int n1, int n2 )


{
int tmp;
tmp = V[n1];
V[n1] = V[n2];
V[n2] = tmp;
}

Gquick(N) = c1 N + Gquick(q) + Gquick(N-q-1) se N > 0


c2 se N == 0

da cui segue la complessità è O(Nln2(N)) nel caso medio ed ottimo (pivot sempre in posizione mediana) e O(N2)
nel caso peggiore (pivot sempre agli estremi dell'array).

Esercizio 4.

struct list {
int value;
struct list * next_ptr;
};

int complete_list( struct list ** ptr1, struct list ** ptr2 ) {


int added = 0, prev_value = 0;
struct list * tmp1, * tmp2;

while ( *ptr1 != NULL ) {


while ( *ptr2 != NULL && (*ptr2)->value < (*ptr1)->value ) {
if ( (*ptr1)->value > (*ptr2)->value && (*ptr2)->value > prev_value) {
printf( "\naggiunto %d", (*ptr2)->value );
prev_value = (*ptr2)->value;
added ++;
// scollega elemento da lista 2
tmp2 = *ptr2;
*ptr2 = (*ptr2)->next_ptr;
// collega a lista 1
tmp1 = *ptr1;
*ptr1 = tmp2;
(*ptr1)->next_ptr = tmp1;
}
else { // avanza all'elemento successivo
ptr2 = &((*ptr2)->next_ptr);
}
}
prev_value = (*ptr1)->value;
ptr1 = &((*ptr1)->next_ptr);
}

// copia eventuali elementi rimasti in lista 2 maggiori di quelli in lista 1


if ( *ptr2 != NULL ) {
tmp2 = *ptr2;
*ptr2 = NULL;
*ptr1 = tmp2;
}
return added;
}

G(N) = c1 * N + c2 N, N > 0, cioè la complessità vale: O(N).

Potrebbero piacerti anche