Introduzione alla LOGICA MATEMATICA Corso di Matematica Discreta. Corso di laurea in Informatica. Prof. Luigi Borzacchini VIII. Insiemi e Strutture Dati
Insiemi come strutture dati Insiemi, matrici e relazioni sono concetti fondamentali non solo in matematica ma anche nello studio delle strutture dati nella computer science. Ogni linguaggio di programmazione ha il suo modo di implementarle, ma la loro struttura logico-algebrica è indipendente dal particolare linguaggio. Le operazioni sono o interne alla struttura dati, come le ordinarie operazioni algebriche (ad esempio in ESSE3 estrarre un dato relativo ad uno studente dalla base di dati), o sulla struttura per cambiarla, come le operazioni insiemistiche (ad esempio aggiungere un nuovo studente alla base di dati di ESSE3).
Il record Di norma le strutture dati sono ordinate dai numeri interi, così che la struttura base è il record a, cioè una sequenza di n elementi o n-upla (a 1, a 2,…., a n ). Scriveremo anche a i come a[i], ove gli a i possono appartenere ad insiemi diversi M i, e quindi il record è un elemento del prodotto cartesiano M 1 M 2 … M n, in cui a 1 M 1, a 2 M 2 ….., a n M n, Possiamo considerare ad esempio il data-base di ESSE3. In esso probabilmente ad ogni studente è associato un record che contiene le informazioni a lui relative.
Un record a può essere ad esempio una sequenza di informazioni personali di uno studente: (Michele, Rossi, , Bari), in cui i diversi ‘campi’ contengono informazioni di diverso tipo: (nome, cognome, data di nascita, luogo di nascita). Nel nostro esempio ESSE3 M 1 può essere l’insieme dei Nomi, M 2 l’insieme dei Cognomi, M 3 l’insieme delle date di nascita, M 4 l’insieme dei luoghi di nascita, etc.. Si usa anche la notazione a:slot value, cioè a 2 = a[cognome] =Rossi, a 1 = a[nome]=Michele, etc., ed il record appare allora come una funzione a j = a[j-esimo tipo] = t M j
L’ array Si può costruire una sequenza di records, ad esempio in ESSE3 ognuno relativo ad uno studente: è l’array. Il record è detto anche l’array monodimensionale. Il concetto di array A infatti generalizza il concetto di record ed equivale alla nostra definizione di matrice: una matrice n m corrisponde allora ad un array bidimensionale formato da n records, ciascuno con m campi: in ESSE3 ci sono n studenti per ciascuno dei quali sono memorizzati m campi di dati. L’i-esima riga di A è il record dei dati dell’i-esimo studente, A[i,j], ovvero A i,j è il valore del j-esimo campo per l’i-esimo studente, A i,j M j
ROSSIPAOLO26/07/ TraniVia Matteotti 6informatica BIANCHIANNA21/10/ BariVia Amendola 3lettere LORUSSONICOLA03/05/ MolaCorso Italia 33lingue RENZIMATTEO12/12/ BariVia Cavour 21informatica CASSANOANTONIO04/06/ RuvoPiazza Roma 6fisica LORUSSOPIETRO11/09/ PaloVia Garibaldi 12informatica CONTEANTONIO22/03/ BariVia Napoli 71informatica BELLUCCIMONICA30/01/ BariPiazza Moro 18biologia GRILLOGIUSEPPE18/02/ MolaVia Cairoli 60informatica BERLUSCONISILVIO24/07/ BariVia Putignani 11informatica matricola, cognome, nome, data di nasc., anno imm., città resid., indirizzo, laurea Come operazione interna alla struttura posso ‘interrogare’ il data-base per sapere quando si è immatricolato lo studente NICOLA LORUSSO. Ed allora devo trovare i records con A[i,2]= Lorusso A[i,3]=Nicola. Se non ci sono omonimi la relazione è funzionale e troverò i* (3 nel nostro esempio, caratterizzato dalla matricola ). E quindi cercherò A[i*,5] (trovandolo uguale a ).
Un array bidimensionale con la specificazione degli n tipi di dati M i che devono essere usati nei vari campi è spesso detto una base di dati relazionale. Infatti esso può essere visto come una relazione n- aria sul prodotto cartesiano M 1 M 2 M 3 …. M n Gli studenti possono comparire in altri data-base (ad esempio relativi agli esami) e per identificarli nei due data base occorre avere una ‘chiave’ univoca (il numero di matricola elemento di M 1 ). Questo vuol dire che la nostra relazione deve essere funzionale in M 1, cioè dato i M 1, deve essere univocamente determinato il record ad esso relativo.
715/09/ ROSSIPAOLO no 915/09/ RENZIMATTEO si 1215/09/ RUSSOPIETRO no 1820/09/ CONTEANTONIO no 1920/09/ GRILLOGIUSEPPE si 2320/09/ BERLUSCONISILVIO si n.ro, data, matricola, cognome, nome, anno immatr., CFU, voto, flag Supponiamo di avere i data-base relativi agli esami, ad esempio Matematica Discreta. Il numero di matricola ci consente di vedere che lo studente Paolo Rossi, matricola , ha preso 28: possiamo così incrociare diversi data-base e ricavare da essi il curriculum di uno studente. I dati possono essere anche utilizzati come input per algoritmi: ad esempio si può calcolare il voto medio degli studenti con una certa residenza o immatricolati un certo anno.
Code e Stacks La struttura del record è la base per tipi di dati più specifici per il tipo di operazioni insiemistiche su di essi. Ad esempio le code e gli stacks si caratterizzano per avere operazioni particolari per l’aggiunta e l’estrazione di dati. La coda (queue) è detta anche first-in-first-out, FIFO, poiché gli elementi si aggiungono alla fine del record e si estraggono al suo inizio. Sia C la coda: Il primo elemento ad essere estratto sarà a, l’ultimo ad essere stato inserito sarà l. Più precisamente abcdefghil
‘mettere in coda’, enquieu: M Code Code enquieu(m,C)= ‘estrarre dalla coda’, dequieu: Code M Code dequieu(C)= (a, Analogo è lo stack, detto anche last-in-first-out, LIFO, poiché sia l’estrazione che l’aggiunta degli elementi avviene sulla fine del record. Sia C lo stack: Le operazioni base sugli stacks sono usualmente denominate con push (aggiungi allo stack) e pop (elimina dallo stack), così definite push(m,C)= pop(C)= (l, abcdefghilm bcdefghil abcdefghil abcdefghilm abcdefghi ) )
Grafi e alberi Sia V un insieme di elementi (vertici), e E un insieme di coppie di vertici (archi), con |V|=n e |E|=m. La coppia (V,E) si dice grafo, diretto se le coppie sono ordinate, indiretto se non lo sono. a a b b c d c d e f Una sequenza di archi (a 1, a 2 ),(a 2, a 3 ), …,(a i-1, a i ),…,(a n-1, a n ), si dice una catena, un cammino se il grafo è diretto; un ciclo se a 1 = a n, un circuito se il grafo è diretto. Un cammino (circuito) si dice hamiltoniano se passa una e una sola volta per tutti i vertici, euleriano se passa una e una sola volta per tutti gli archi.
Abbiamo usato i grafi diretti per rappresentare le relazioni binarie, gli alberi per le tassonomie. Un grafo senza cicli si dice un albero. Se in un albero scegliamo un vertice come radice e ordiniamo da esso tutti i vertici, l’albero viene univocamente ordinato (verso il basso) a partire dalla radice. Gli a b c d e f g si dicono foglie. Nell’albero in figura sia d o b la radice e ordiniamo l’albero, ottenendo l’albero diretto: d b c f g c d a e a b f g e In un albero m=n-1
I grafi si rappresentano in genere tramite matrici. La matrice di incidenza M è n m, definita come M i,j = 1 sse il vertice i l’arco j, 0 altrimenti (per grafi indiretti), oppure M i,j = +1 se i è vertice terminale di j, M i,j = -1 se è vertice iniziale, 0 altrimenti (per grafi diretti). La matrice di adiacenza A è n n, definita come A i,j = 1 sse l’arco (i,j) E, 0 altrimenti (per grafi indiretti A è simmetrica). a b c d e f abcdefabcdef abcdefabcdef M A
a b c d e f e d f c b a g abcdefabcdef abcdefabcdef M A Importante l’ordine di esplorazione di un albero: si può usare la depth first, in cui si scende lungo i rami, memorizzando le diramazioni, da esplorare quando un ramo sia terminato (backtracking). Un’altra tecnica è la breadth first, in cui si esplorano i livelli in successione, ma occorre memorizzare tutta l’esplorazione precedente.