Lezione 8 Struct e qsort

Documenti analoghi
Lezione 9 Esercizi d esame

Lezione 6 Selection/Insertion Sort su interi e stringhe

Complementi. - Ridefinizione di tipo - - Costrutto switch - - Programmazione su più file - - Parametri della funzione main - Funzione system -

Lezione 5 Sottoarray di somma massima

Struct, enum, Puntatori e Array dinamici

Puntatori a Funzioni e Callback. Massimo Benerecetti

Informatica 1. Corso di Laurea Triennale in Matematica. Gianluca Rossi

Esercitazione 12. Esercizi di Ricapitolazione

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

ELEMENTI DI INFORMATICA L-B. Ing. Claudia Chiusoli

Linguaggio C. Generalità sulle Funzioni. Variabili locali e globali. Passaggio di parametri per valore.

Lezione 8. Sottoprogrammi

Programmazione I - Laboratorio

Scrittura formattata - printf

I puntatori e l allocazione dinamica di memoria. Esercizi risolti

ARRAY E STRINGHE. ESERCIZIO 2 Scrivere un programma che calcola il numero di doppie e di dittonghi (2 vocali vicine) presenti in una stringa.

Esercizio 1: funzione con valore di ritorno di tipo puntatore

Allocazione Dinamica. Allocazione Statica. malloc() La funzione malloc()

INFORMATICA DI BASE Linguaggio C Prof. Andrea Borghesan

I puntatori. Un puntatore è una variabile che contiene l indirizzo di un altra variabile. puntatore

Stringhe e allocazione dinamica della memoria

Non ci sono vincoli sul tipo degli elementi di un vettore Possiamo dunque avere anche vettori di

Array. Maurizio Palesi Salvatore Serrano. In C si possono definire tipi strutturati Vi sono due costruttori fondamentali

Strutture dati dinamiche in C (II)

4 Le liste collegate 4.0. Le liste collegate. 4 Le liste collegate Rappresentazione di liste 4.1 Rappresentazione di liste

Alberi binari e alberi binari di ricerca

Tipi di dati strutturati e Linguaggio C. Record o strutture Il costruttore struct in C

ESECUZIONE DI PROGRAMMI C SU MACCHINE REALI. Docente: Giorgio Giacinto AA 2008/2009. formalizzazione degli algoritmi in linguaggio C

ERRATA CORRIGE. void SvuotaBuffer(void); void SvuotaBuffer(void) { if(getchar()!=10) {svuotabuffer();} }

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Caratteri e stringhe

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Informatica 1. Prova di recupero 21 Settembre 2001

Funzioni e. Alessandra Giordani Mercoledì 16 maggio 2012

Esercizio 2 (punti 7) Dato il seguente programma C: #include <stdio.h> int swap(int * nome, int length);

Dati aggregati. Violetta Lonati

Puntatori. Obiettivi: Richiamare quanto noto sui puntatori dal modulo A Presentare l analogia tra puntatori e vettori e l aritmetica dei puntatori

Definizione Allocazione e deallocazione di variabili Allocazione e deallocazione di vettori

Gestione dinamica della memoria

Introduzione ai puntatori in C Definizione

Programmazione I - Laboratorio

Linguaggio C: puntatori

Breve Manuale di Riferimento sulla Sintassi Linguaggi C++ e FORTRAN

Le strutture. Una struttura C è una collezione di variabili di uno o più tipi, raggruppate sotto un nome comune.

Scope delle variabili e passaggio parametri. Danilo Ardagna Politecnico di Milano

Esercitazione 5. Procedure e Funzioni Il comando condizionale: switch

Linguaggio C - Strutture

Strategie di programmazione

Array multidimensionali e stringhe

ESECUZIONE DI PROGRAMMI C SU MACCHINE REALI. Docente: Giorgio Giacinto AA 2009/2010

Lezione 9: Puntatori a funzioni. Tipi enumerativi e orientati ai bit

L Allocazione Dinamica della Memoria

FONDAMENTI DI INFORMATICA

Un esempio per iniziare. Il controllo del programma in C. Altri cenni su printf() Esercizi (printf) printf( 8!=%d, fatt);

Alberi e alberi binari I Un albero è un caso particolare di grafo

Ottenere una modifica del parametro attuale

Unità Didattica 5 Linguaggio C. Stringhe. Accesso a file ASCII. Strutture.

Puntatori. Fondamenti di Programmazione

Fondamenti di Informatica e Laboratorio T-AB T-16 Progetti su più file. Funzioni come parametro. Parametri del main

Esercizi C su array e matrici

Esercizi di programmazione in linguaggio C English Dictionary

giapresente( ) leggi( ) char * strstr(char * cs, char * ct) NULL

Elementi lessicali. Lezione 4. La parole chiave. Elementi lessicali. Elementi lessicali e espressioni logiche. Linguaggi di Programmazione I

Tipi di dato personalizzati Array di struct. Tipi di dato utente. Laboratorio di Programmazione I. Corso di Laurea in Informatica A.A.

! Per quanto sappiamo finora, in C le variabili sono sempre definite staticamente

Passare argomenti al programma

Tipi di dati fondamentali. Tipi di dati fondamentali. Utilità dei tipi di dati nelle dichiarazioni. Il tipo di dati char. Codice ASCII.

Linguaggio C. Esercizio 1

La gestione della memoria dinamica Heap

Fondamenti di Informatica T-1 Modulo 2

Laboratorio di Informatica

LIBRERIE STANDARD in C. LIBRERIE STANDARD in C

Esercizi. Stringhe. Stringhe Ricerca binaria

Laboratorio di Algoritmi e Strutture Dati

Algoritmi e basi del C Struttura di un programma

Esercitazione 6. Array

Tipi di dato. Le variabili in C. Problema: dato in input un carattere, se esso è una lettera minuscola, trasformarla in maiuscola.

Capitolo 7 I puntatori in C

Alberi ed Alberi Binari

Strutture Dati. Elisa Marengo. Università degli Studi di Torino Dipartimento di Informatica. Elisa Marengo (UNITO) Strutture Dati 1 / 16

Programmazione in Java (I modulo)

Lab 10 Passaggio per riferimento

Mini-dispensa sui puntatori in C

Linguaggi di programmazione + laboratorio a.a. 2012/2013

Linguaggio C Struct e union

Prof. E. Occhiuto INFORMATICA 242AA a.a. 2010/11 pag. 1

Argomenti della lezione. Introduzione agli Algoritmi e alle Strutture Dati. Lista Lineare. Lista Lineare come Tipo di Dato Astratto

LABORATORIO DI FONDAMENTI DI INFORMATICA DIAGRAMMI DI FLUSSO E CODIFICA IN C DEGLI ALGORITMI

Prova di Laboratorio del [ Corso A-B di Programmazione (A.A. 2004/05) Esempio: Media Modalità di consegna:

Il linguaggio C. Puntatori e dintorni

Per semplicità eliminiamo le ripetizioni nell'albero.

Introduzione al C. Unità 8 Stringhe

s r t i r n i g n. g h s r t c r p c y s r t c r a c t s r t c r m c p s r t c r h c r s r t s r t s r

Tempo di vita e scope delle variabili

Puntatori. Un puntatore contiene un numero che indica la locazione di memoria dove è presente la variabile puntata

Funzioni, puntatori, strutture. Lab. Calc. AA 2006/07

Esempio di Prova Scritta

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

Esercizio 1. Esercizio 1 Soluzione

Funzioni, Stack e Visibilità delle Variabili in C

Transcript:

Lezione 8 Struct e qsort Rossano Venturini rossano@di.unipi.it Pagina web del corso http://didawiki.cli.di.unipi.it/doku.php/informatica/all-b/start

Esercizio 3 QuickSort strambo Modificare il Quicksort del primo esercizio in maniera tale che ordini gli elementi pari nella parte inferiore dell array e quelli dispari in quella superiore. Scrivere un programma che utilizzi la funzione per ordinare come indicato un array di N interi letti da input. La prima riga dell input contiene la dimensione N (non limitata) dell array. Le righe successive contengono gli elementi dell array, uno per riga. L output contiene la sequenza ordinata, su una sola riga.

Esercizio 3 int confronta(int val1, int val2) { int mod1, mod2;! /* L'ordinamento tra un pari e un dispari viene riflesso tra le loro classi di * resto modulo 2. */ mod1 = abs(val1 % 2); mod2 = abs(val2 % 2); if (mod1!= mod2) return mod1 - mod2; return val1 - val2; }

Esercizio 3 int distribuzione(int a[], int sx, int px, int dx) { int i, j;! if (px!= dx) scambia(a, px, dx);! i = sx; j = dx - 1; while (i <= j) { while ( (i <= j) && (confronta(a[i], a[dx]) <= 0) ) i++; while ( (i <= j) && (confronta(a[j], a[dx]) >= 0) ) j--; if (i < j) scambia(a, i, j); } if (i!= dx) scambia(a, i, dx); return i; }

Struct

Struct Fino ad ora abbiamo utilizzato tipi semplici (char, int, float, ), puntatori (char *, int *, float *, ) o array di tipi semplici

Struct Fino ad ora abbiamo utilizzato tipi semplici (char, int, float, ), puntatori (char *, int *, float *, ) o array di tipi semplici Spesso è utile avere tipi complessi: tipi ottenuti combinando tipi semplici

Struct Fino ad ora abbiamo utilizzato tipi semplici (char, int, float, ), puntatori (char *, int *, float *, ) o array di tipi semplici Spesso è utile avere tipi complessi: tipi ottenuti combinando tipi semplici Esempi: - coordinate di un punto nel un piano (coordinate x e y); - nodo di un albero (chiave e puntatori ai figli); - elementi di una lista (chiave e puntatori al predecessore e successore).

Struct Fino ad ora abbiamo utilizzato tipi semplici (char, int, float, ), puntatori (char *, int *, float *, ) o array di tipi semplici Spesso è utile avere tipi complessi: tipi ottenuti combinando tipi semplici Esempi: - coordinate di un punto nel un piano (coordinate x e y); - nodo di un albero (chiave e puntatori ai figli); - elementi di una lista (chiave e puntatori al predecessore e successore). Le struct consentono la creazione di nuovi tipi. Ad esempio, un punto è un tipo avente due campi: x e y.

Struct Fino ad ora abbiamo utilizzato tipi semplici (char, int, float, ), puntatori (char *, int *, float *, ) o array di tipi semplici Spesso è utile avere tipi complessi: tipi ottenuti combinando tipi semplici Esempi: - coordinate di un punto nel un piano (coordinate x e y); - nodo di un albero (chiave e puntatori ai figli); - elementi di una lista (chiave e puntatori al predecessore e successore). Le struct consentono la creazione di nuovi tipi. Ad esempio, un punto è un tipo avente due campi: x e y. struct point { int x; int y; };

Struct Fino ad ora abbiamo utilizzato tipi semplici (char, int, float, ), puntatori (char *, int *, float *, ) o array di tipi semplici Spesso è utile avere tipi complessi: tipi ottenuti combinando tipi semplici Esempi: - coordinate di un punto nel un piano (coordinate x e y); - nodo di un albero (chiave e puntatori ai figli); - elementi di una lista (chiave e puntatori al predecessore e successore). Le struct consentono la creazione di nuovi tipi. Ad esempio, un punto è un tipo avente due campi: x e y. struct point { int x; int y; }; NB. una struct può avere campi di tipi diversi, anche altre struct.

Struct Fino struct ad ora point abbiamo { utilizzato tipi semplici (char, int, float, ), puntatori int x; (char *, int *, float *, ) o array di tipi semplici Spesso int è y; utile avere tipi complessi: tipi ottenuti combinando tipi semplici Esempi: };!- coordinate di un punto nel un piano (coordinate x e y); int - nodo main() di un { albero (chiave e puntatori ai figli); - elementi di una lista (chiave e puntatori al predecessore e successore). struct point p; //dichiarazione Le struct p.x = consentono 10; //accesso la creazione ad un campo di nuovi con tipi.. Ad esempio, un punto è un tipo avente due campi: x e y. p.y = 14; struct printf( Posizione point { x %d, y %d, p.x, p.y); return int x; 0; } int y; }; NB. una struct può avere campi di tipi diversi, anche altre struct.

Struct: puntatori e allocazione Un puntatore a struct è dichiarato come per le altre variabili.

Struct: puntatori e allocazione Un puntatore a struct è dichiarato come per le altre variabili. struct point { int x; }; int y; int main() { struct point *p; // dichiarazione

Struct: puntatori e allocazione Un puntatore a struct è dichiarato come per le altre variabili. struct point { int x; }; int y; int main() { struct point *p; // dichiarazione p = (struct point *) malloc(sizeof(struct point)); // allocazione

Struct: puntatori e allocazione Un puntatore a struct è dichiarato come per le altre variabili. struct point { int x; }; int y; int main() { struct point *p; // dichiarazione p = (struct point *) malloc(sizeof(struct point)); // allocazione (*p).x = 10; // assegnamento CORRETTO

Struct: puntatori e allocazione Un puntatore a struct è dichiarato come per le altre variabili. struct point { int x; }; int y; int main() { struct point *p; // dichiarazione p = (struct point *) malloc(sizeof(struct point)); // allocazione (*p).x = 10; // assegnamento CORRETTO p->x = 10; // equivalente al precedente

Struct: puntatori e allocazione Un puntatore a struct è dichiarato come per le altre variabili. struct point { int x; }; int y; int main() { struct point *p; // dichiarazione p = (struct point *) malloc(sizeof(struct point)); // allocazione (*p).x = 10; // assegnamento CORRETTO p->x = 10; // equivalente al precedente p[0].x = 10; // equivalente ai precedenti

Struct: puntatori e allocazione Un puntatore a struct è dichiarato come per le altre variabili. struct point { int x; }; int y; int main() { struct point *p; // dichiarazione p = (struct point *) malloc(sizeof(struct point)); // allocazione (*p).x = 10; // assegnamento CORRETTO p->x = 10; // equivalente al precedente p[0].x = 10; // equivalente ai precedenti *p.x = 10; // Errato!. ha la precedenza su *

Struct e funzioni (1) Una funzione può restituire una struct, esattamente come con gli altri tipi. struct point { int x; int y; };! struct point createpoint(int x, int y) { struct point p; p.x = x; p.y = y; return p; }

Struct e funzioni (2) Una struct può essere passata (per valore) come parametro ad una funzione struct point { int x; int y; };! struct point sumpoint(struct point p1, struct point p2) { p1.x = p1.x + p2.x; // si opera direttamente su p1 p1.y = p1.y + p2.y; // ma il chiamante vede le modifiche? return p1; }

Struct e funzioni (3)

Struct e funzioni (3) In molti casi è necessario o preferibile passare il puntatore ad una struct anziché la struct stessa:

Struct e funzioni (3) In molti casi è necessario o preferibile passare il puntatore ad una struct anziché la struct stessa: - quando vogliamo modificare i campi della struct (necessario);

Struct e funzioni (3) In molti casi è necessario o preferibile passare il puntatore ad una struct anziché la struct stessa: - quando vogliamo modificare i campi della struct (necessario); - quando la dimensione della struct è grande e la copia dei suoi campi sarebbe troppo costosa (preferibile).

Struct e funzioni (3) In molti casi è necessario o preferibile passare il puntatore ad una struct anziché la struct stessa: - quando vogliamo modificare i campi della struct (necessario); - quando la dimensione della struct è grande e la copia dei suoi campi sarebbe troppo costosa (preferibile). void swappoint(struct point* p){ int tmp=p->x; p->x=p->y; p->y=tmp; }! int main(){ struct point* p = (struct point *) malloc(sizeof(struct_point)); p->x = 5; p->y = 2; swappoint(p); printf( x %d, y %d, p->x, p->y); }

Typedef

Typedef In C è possibile assegnare nuovi nomi ai tipi di dato. typedef tipo nuovo_nome; Non viene creato un nuovo tipo ma solo un alias.

Typedef In C è possibile assegnare nuovi nomi ai tipi di dato. typedef tipo nuovo_nome; Non viene creato un nuovo tipo ma solo un alias. Esempi typedef char* string; Ora string può essere usato al posto di char *

Typedef In C è possibile assegnare nuovi nomi ai tipi di dato. typedef tipo nuovo_nome; Non viene creato un nuovo tipo ma solo un alias. Esempi typedef char* string; Ora string può essere usato al posto di char * typedef struct _punto { int x; int y; } punto; Ora punto può essere usato al posto di struct _punto

Struct ricorsive Una struct può avere come campo un puntatore alla struct stessa. Esempio typedef struct _node { int key; struct _node *next; } node;

Qsort La libreria standard (includere stdlib.h) ha una implementazione del QuickSort pensata per ordinare qualunque tipo di dato.

Qsort La libreria standard (includere stdlib.h) ha una implementazione del QuickSort pensata per ordinare qualunque tipo di dato. void qsort( void *buf, size_t num, size_t size, int (*compare) (const void *, const void *) );

Qsort La libreria standard (includere stdlib.h) ha una implementazione del QuickSort pensata per ordinare qualunque tipo di dato. void qsort( void *buf, size_t num, size_t size, int (*compare) (const void *, const void *) ); void *buf: puntatore al primo elemento dell array da ordinare;

Qsort La libreria standard (includere stdlib.h) ha una implementazione del QuickSort pensata per ordinare qualunque tipo di dato. void qsort( void *buf, size_t num, size_t size, int (*compare) (const void *, const void *) ); void *buf: puntatore al primo elemento dell array da ordinare; size_t num: numero di elementi da ordinare;

Qsort La libreria standard (includere stdlib.h) ha una implementazione del QuickSort pensata per ordinare qualunque tipo di dato. void qsort( void *buf, size_t num, size_t size, int (*compare) (const void *, const void *) ); void *buf: puntatore al primo elemento dell array da ordinare; size_t num: numero di elementi da ordinare; size_t size: la dimensione in byte di ciascun elemento;

Qsort La libreria standard (includere stdlib.h) ha una implementazione del QuickSort pensata per ordinare qualunque tipo di dato. void qsort( void *buf, size_t num, size_t size, int (*compare) (const void *, const void *) ); void *buf: puntatore al primo elemento dell array da ordinare; size_t num: numero di elementi da ordinare; size_t size: la dimensione in byte di ciascun elemento; int (*compare) (const void *, const *void): (il puntatore ad) una funzione che specifichi come confrontare due elementi dell array. Attraverso questa funzione si fornisce il criterio per l ordinamento.

Funzione di confronto Il qsort necessita di una funzione per confrontare gli elementi. int compare (const void *, const void *); che dati i puntatori a due elementi restituisca

Funzione di confronto Il qsort necessita di una funzione per confrontare gli elementi. int compare (const void *, const void *); che dati i puntatori a due elementi restituisca < 0: se il primo elemento deve precedere il secondo nell ordinamento;

Funzione di confronto Il qsort necessita di una funzione per confrontare gli elementi. int compare (const void *, const void *); che dati i puntatori a due elementi restituisca < 0: se il primo elemento deve precedere il secondo nell ordinamento; > 0: se il secondo elemento deve precedere il primo nell ordinamento;

Funzione di confronto Il qsort necessita di una funzione per confrontare gli elementi. int compare (const void *, const void *); che dati i puntatori a due elementi restituisca < 0: se il primo elemento deve precedere il secondo nell ordinamento; > 0: se il secondo elemento deve precedere il primo nell ordinamento; = 0: altrimenti.

Funzione di confronto Il qsort necessita di una funzione per confrontare gli elementi. int compare (const void *, const void *); che dati i puntatori a due elementi restituisca < 0: se il primo elemento deve precedere il secondo nell ordinamento; > 0: se il secondo elemento deve precedere il primo nell ordinamento; = 0: altrimenti. Questo tipo di funzione (con nome arbitrario) deve essere implementata a seconda del tipo da ordinare e dell ordinamento desiderato.

Esempio: Interi Ordinare un array di interi in modo non decrescente

Esempio: Interi Ordinare un array di interi in modo non decrescente #include<stdlib.h> #include<stdio.h>

Esempio: Interi Ordinare un array di interi in modo non decrescente #include<stdlib.h> #include<stdio.h> int confrontaint(const void *a, const void *b) { return ( *(int*)a - *(int*)b ); }

Esempio: Interi Ordinare un array di interi in modo non decrescente #include<stdlib.h> #include<stdio.h> int confrontaint(const void *a, const void *b) { return ( *(int*)a - *(int*)b ); } int main(){ int values[] = {10, 21, 1, 7, 24, 9}; int n = 6; qsort(values, n, sizeof(int), confrontaint);

Esempio: Stringhe Ordinare un array di stringhe in ordine lessicografico

Esempio: Stringhe Ordinare un array di stringhe in ordine lessicografico int compare(const void *a, const void *b){ char **a1= (char **) a; char **b1= (char **) b; return strcmp(*a1,*b1); }

Esempio: Stringhe Ordinare un array di stringhe in ordine lessicografico int compare(const void *a, const void *b){ char **a1= (char **) a; char **b1= (char **) b; return strcmp(*a1,*b1); } int main(){ int i; int n=10; char ** values = malloc(n*sizeof(char *)); for(i=0; i < n; i++) { values[i] = malloc(101*sizeof(char)); scanf( %s, values[i]); } qsort(values, n, sizeof(char *), compare);

Esercizio 1 Qsort su interi Scrivere un programma che utilizzi la funzione qsort e ordini un vettore di interi (in input), in modo da ottenere il seguente e etto. L array ordinato deve contenere prima tutti i numeri pari e, a seguire, i numeri dispari. Si assuma che il numero 0 sia pari. I numeri pari devono essere ordinati in modo crescente fra di loro. I numeri dispari devono essere ordinati in modo decrescente fra di loro.

Esercizio 2 Qsort su stringhe Scrivere un programma che legga in input un array A di stringhe e che utilizzi la funzione qsort per ordinare in ordine alfabetico decrescente le stringhe in input. Assumere che la lunghezza massima di una stringa sia 100 caratteri.

Esercizio 3 Qsort e struct Scrivere un programma che utilizzi la funzione qsort per ordinare un vettore di punti del piano cartesiano. Ciascun punto è formato da una coppia di coordinate (x, y). I punti devono essere ordinati per ascissa crescente. A parità di ascissa, si ordini per ordinata decrescente.

Esercizio 4 Qsort su stringhe e struct Scrivere un programma che utilizzi la funzione qsort per ordinare un array di stringhe. Le stringhe devono essere ordinate per lunghezza crescente. A parità di lunghezza, si utilizzi l ordinamento lessicografico. Utilizzare una struct che memorizzi una stringa e la sua lunghezza per evitare di calcolare quest ultima ad ogni confronto.

Elemento maggioritario Puzzle Un array A contiene n interi. Uno di essi è detto elemento maggioritario se occorre in A almeno b n 2 c + 1 volte. Si vuole un algoritmo che identifichi l elemento maggioritario, se presente, in tempo O(n) utilizzando O(1) spazio aggiuntivo. L algoritmo deve stampare N se non è presente alcun elemento maggioritario. Caso particolare. Si assuma che tutti gli elementi, ad esclusione eventualmente del maggioritario, occorrano una sola volta in A. Caso generale. Gli elementi possono avere un numero arbitrario di occorrenze. Input 5 1 10 22 11 2 Input 5 22 10 22 11 22 Output N Output 22

Puzzle Due uova Interview di Google In un palazzo di 100 piani si vuole stabilire qual è il piano più alto dal quale è possibile lanciare un uovo senza che esso si rompa. Le uova sono considerate tutte aventi lo stesso grado di resistenza. Si hanno a disposizione solamente due uova e si vuole individuare tale piano con il minor numero di lanci. Soluzione banale: si provano tutti i piani sequenzialmente dal primo al novantanovesimo. Dopo ogni lancio si prosegue se e soltanto se l uovo appena lanciato risulta ancora intatto. Al caso pessimo sono necessari 99 lanci.