810 likes | 952 Views
CAPITOLO 6 Ordinamento di array e array a più dimensioni. Variabili strutturate Le variabili dei tipi predefiniti del C++ float, double, int, e boolean prendono il nome di variabili scalari .
E N D
CAPITOLO 6 Ordinamento di array e array a più dimensioni Programmazione Mod A - Cap 6 - prof. Burattini
Variabili strutturate • Le variabili dei tipi predefiniti del C++ float, double, int, e boolean prendono il nome di variabili scalari. • Una variabile è invece strutturata se è composta di altre variabili che a loro volta possono essere variabili strutturate o scalari, queste a loro volta sono comunemente chiamate elementi della variabile strutturata. • Ogni variabile strutturata deve possedere un meccanismo o modalità di accesso alle variabili che la compongono in modo che sia possibile riferirsi ad esse ed eventualmente modificarle. Programmazione Mod A - Cap 6 - prof. Burattini
Variabili strutturate • L’array monodimensionale rappresenta il primo tipo di variabile strutturata. • Le sue componenti sono variabili tutte dello stesso tipo ed il meccanismo di accesso consiste di una espressione di tipo intero che viene valutato a run time e sommato all’indirizzo base dell’array per fornire direttamente l’indirizzo della componente voluta (meccanismo di accesso diretto). • In generale un array pur essendo sempre formato da variabili tutte dello stesso tipo può accedere alle sue componenti attraverso un numero finito di espressioni intere. • Si parla in tal caso di array multidimensionali. Particolarmente utili sono gli array bidimensionali altrimenti detti matrici. Programmazione Mod A - Cap 6 - prof. Burattini
Array monodimensionali: ordinamento (sort) Supponiamo che Vet sia una variabile dichiarata come int Vet[10]; essa ha un indice compreso tra 0 e 9. Un array monodimensionale di interi è ordinato in ordine crescente se all’aumentare dell’indice aumenta anche il valore dell’elemento; è ordinato in ordine decrescente se all’aumentare dell’indice il valore dell’elemento diminuisce; per esempio dei tre vettori A=[2, 4, 5, 7, 7, 9, 12, 15] B=[2, 5, 8, 3, 7, 11] C=[15, 9, 8, 6, 5, 5, 3, 1] A è ordinato in ordine crescente, C lo è in ordine decrescente, B non è ordinato. Programmazione Mod A - Cap 6 - prof. Burattini
Tenendo presente che un vettore di dimensione 1 è sempre ordinato, per un vettore di dimensione N>1 possiamo dare le seguenti definizioni: Gli elementi di un vettore sono ordinati in ordine crescente se e solo se per ogni indice i compreso tra 0 e N -2 si ha Vettore[ i ]<=Vettore[i+1]. Gli elementi del vettore sono ordinati in ordine decrescente se e solo se per ogni indice i compreso tra 0 e N -2 si ha Vettore[ i ]>=Vettore [i+1]. Le stesse definizioni possono valere sia per i numeri reali (float o double) che per le stringhe. Programmazione Mod A - Cap 6 - prof. Burattini
L’ordinamento per le stringhe è, di solito, quello lessicografico (l’ordine alfabetico) che rispecchia l’ordine ASCII; in questo caso è necessario anche tener presente che tutte le lettere maiuscole precedono tutte quelle minuscole per cui una parola che inizia con lettera maiuscola precede le altre: andare precede correre ma andare segue Correre Per questo motivo prima di ordinare lessicograficamente un insieme di parole che possono iniziare anche con una lettera maiuscola occorre convertire tale carattere iniziale in minuscolo prima di eseguire il confronto. Programmazione Mod A - Cap 6 - prof. Burattini
10 1 19 2 9 9 3 10 30 4 12 29 5 18 12 6 19 18 7 29 30 ORDINAMENTO = SORTING Programmazione Mod A - Cap 6 - prof. Burattini
Tutti ordinati Supponiamo di voler ordinare in modo crescente gli elementi dell’array vet; a questo scopo definiamo la seguente procedura: void Ordina (int[] vet, int N) { IN : Vettore di interi di dimensione N non ordinato OUT : Vettore di interi ordinato in modo crescente } Un possibile modo di risolvere il problema dell’ordinamento è pensare di dover iterare la seguente situazione: siamo in uno stato in cui nel nostro vettore si trovano già nel loro posto definitivo i primi k elementi, che quindi nel vettore occupano le posizioni da zero a k-1. Operiamo in modo da portare nella posizione k l’elemento giusto Tutti di valore maggiore agli ordinati 0 1 ………… k-1 k ………………… N-2 N-1 Programmazione Mod A - Cap 6 - prof. Burattini
0 1 ………… k-1 k ………………… N-2 N-1 Gli elementi compresi tra 0 e k-1 sono non solo ordinati in ordine crescente, ma sono anche inseriti nella loro posizione definitiva; gli elementi da k in poi, anche se sono disordinati, sono comunque maggiori di quelli compresi tra 0 e k-1. Possiamo affermare in definitiva che sono ordinati i primi k+1 elementi (compresi tra 0 e k). Scriviamo il ciclo: for (k=0; k<N-1;k++) porta l’elemento giusto nella posizione k k è inizializzato a 0 dunque porta l’elemento giusto nella posizione k è banalmente soddisfatto poiché un solo elemento non può essere disordinato (anche se in generale non sarà l’elemento più piccolo). Inoltre esso è ovviamente soddisfatto per definizione in uscita da ogni passo. Dopo l’ultimo passo k è diventato N-1 il che significa che l’intero vettore è ordinato allorché si esce dal ciclo. Programmazione Mod A - Cap 6 - prof. Burattini
Tutti ordinati Tutti di valore maggiore agli ordinati 0 1 ………… k-1 k ………………… N-2 N-1 Per “portare l’elemento giusto nella posizione k” occorrerà in qualche modo scorrere la seconda parte dell’array , quella ancora disordinanta da k in poi, dunque occorrerà un altro loop. Programmazione Mod A - Cap 6 - prof. Burattini
BUBBLE SORT La tecnica adoperata nel bubble sort per portare in posizione k il più piccolo degli elementi compresi tra gli indici k..N-1, consiste nello scambiare di posto tutte le coppie adiacenti ‘disordinate’ partendo dall’indice N-2 fino ad arrivare all’indice k for(k=0; k<N-1; k++) Ciclo esterno: Incrementa k solo quando tutti gli elementi da 0 a k sono ordinati in via definitiva for (j=N-2; j>=k; j--) Ciclo Interno: cerca il più piccolo dei valori di vet[j] compresi tra N-2 e k if (vet[j] > vet[j+1])allora scambia (vet[j],vet[j+1]); Al termine del ciclo interno sarà verificata la condizione: vet[k] è il più piccolo tra tutti gli elementi compresi tra k ed N-1. Inoltre altri elementi si saranno avvicinati alla loro posizione definitiva. Programmazione Mod A - Cap 6 - prof. Burattini
k=0 k=1 k=2 k=3 10 10 9 9 9 9 9 19 19 10 10 10 10 10 9 9 19 19 12 12 12 30 12 12 12 19 18 19 29 30 30 18 18 19 18 12 29 29 30 30 29 29 18 18 18 29 29 30 30 10 10 9 9 9 9 9 9 9 19 19 10 10 10 10 10 10 10 9 9 19 19 12 12 12 12 12 30 12 12 12 19 19 19 19 18 29 30 30 30 18 18 18 18 19 12 29 29 18 30 29 29 29 29 18 18 18 29 29 30 30 30 30 9 10 10 9 9 9 10 19 9 10 10 10 12 9 19 19 12 12 30 19 12 12 19 19 12 18 30 18 18 18 29 30 29 30 29 29 18 29 18 29 30 30 j=N-2 Programmazione Mod A - Cap 6 - prof. Burattini
9 9 9 10 10 10 12 12 12 18 18 18 19 19 19 29 29 9 29 30 30 10 30 12 18 9 19 9 10 29 10 12 30 12 18 18 19 19 29 29 30 30 k=5 k=6 k=4 N° confronti: (n-1)+(n-2)+…+1=(n-1)*n/2 Programmazione Mod A - Cap 6 - prof. Burattini
L’algoritmo è composto da due cicli nidificati. Applichiamolo al seguente esempio: indici 0, 1, 2, 3, 4 vet = [6, 8, 11, 5, 7] CICLO ESTERNO k=0 CICLO INTERNO j=3 vet[3] > vet[4] : NO lascia il vettore invariato j=2 vet[2] > vet[3] : SI scambia gli elementi; il vettore diventa: [6, 8, 5,11, 7] j=1 vet[1] > vet[2] : SI scambia gli elementi; il vettore diventa: [6, 5 ,8, 11, 7] j=0 vet[0] > vet[1] : SI scambia gli elementi; il vettore diventa: [5, 6 ,8, 11, 7] CICLO ESTERNO k=1 CICLO INTERNO j=3 vet[3] > vet[4] : SI scambia gli elementi; il vettore diventa: [5, 6 ,8, 7, 11 ] j=2 vet[2] > vet[3] : SI scambia gli elementi; il vettore diventa [5, 6, 7, 8, 11] j=1 vet[1] > vet[2] : NO lascia il vettore invariato Notiamo che in questo caso non solo i primi due elementi sono già nella loro posizione definitiva, come richiesto, ma anche gli altri. Nelle successive iterazioni non ci saranno altri scambi. Programmazione Mod A - Cap 6 - prof. Burattini
ESERCIZI • Scrivere una procedura Bubble-Sort. • Utilizzando la libreria sui vettori, scrivere un programma che provi l’algoritmo. • Il main del programma potrebbe essere il seguente: • dichiara un vettore v di interi con massimo 100 elementi; • inserisce la dimensione N del vettore in input; • Richiama la procedura di riempimento dei primi N-1 posti del vettore • richiama la procedura di ordinamento; • richiama la procedura di stampa. • Velocizzare il programma precedente introducendo un controllo nel loop interno per registrare se è avvenuto almeno uno scambio; se non c’è stato nessuno scambio significa che il vettore è già ordinato ed il loop esterno può essere interrotto. • 2. Adoperare la tecnica del bubble sort per trasformare il vettore in uno contenente prima i numeri pari seguiti da tutti i numeri dispari. • 3. Trasformare il vettore in uno contenente all’inizio tutti gli zeri, seguiti da tutti i negativi e terminante con i numeri positivi. Programmazione Mod A - Cap 6 - prof. Burattini
SELECTION SORT Usa lo stesso ciclo esterno del bubble sort, mentre per portare l’elemento giusto al posto k determina dapprima l’indice dell’elemento più piccolo tra i numeri di indice da k a N-1 ed in uscita dal ciclo lo scambia con l’elemento in posizione k for (k=0; k<N-1;k++) { // Ciclo Esterno // PRE: gli elementi da 0 a k-1 sono nella loro posizione definitiva IndiceMinimo k ; // // Ciclo Interno for (j=k+1; j< N ; j++) // se l’elemento di ordine j è più piccolo di quello di if vet[j] < vet[IndiceMinimo] // ordine IndiceMinimo, allora IndiceMinimo di IndiceMinimo j; // il j-esimo elemento. Alla fine del ciclosi scambia Scambia(vet[k], vet[IndiceMinimo];//l’elemento di ordine IndiceMinimo con quello di ordine // k in modo che sia verificata la postcondizione: //POST: vet[k] è il più piccolo di tutti gli elementi compresi tra k ed N e dunque tutti gli elementi da 0 a k sono nella loro posizione definitiva. Programmazione Mod A - Cap 6 - prof. Burattini
1 1 1 1 1 1 10 10 10 10 10 10 19 19 19 19 19 19 1 3 9 9 9 9 9 9 3 30 30 30 30 30 30 3 29 29 29 29 29 29 3 12 12 12 12 12 12 3 18 18 18 18 18 18 9 9 9 9 9 2 2 2 2 2 19 19 19 19 19 10 10 10 10 10 3 3 30 30 30 30 30 3 29 29 29 29 29 3 12 12 12 12 12 3 18 18 18 18 18 9 9 9 9 10 10 10 10 3 3 3 3 19 19 19 19 30 30 30 30 3 3 29 29 29 29 6 12 12 12 12 6 18 18 18 18 k=0 k=1 k=2 SELECTION SORT Programmazione Mod A - Cap 6 - prof. Burattini
9 9 9 10 10 10 12 12 12 4 4 4 30 30 30 29 29 29 5 6 19 19 19 7 18 18 18 9 9 10 10 12 12 18 18 5 5 30 29 29 30 7 19 19 6 9 9 10 10 12 12 18 18 19 19 6 30 29 7 29 30 7 k=3 k=4 N° confronti: (n-1)+(n-2)+…+1=(n-1)*n/2 k=5 SELECTION SORT Programmazione Mod A - Cap 6 - prof. Burattini
ESERCIZIO Scrivere una procedura per l’algoritmo di Selection-Sort. In seguito, utilizzando la libreria sui vettori, scrivere un programma che provi l’algoritmo. Programmazione Mod A - Cap 6 - prof. Burattini
Insertion Sort Questo algoritmo di ordinamento è il più intuitivo dei tre presentati essendo molto simile al modo in cui operiamo manualmente. E’ l’algoritmo più intuitivo. Se ad esempio si ha un mazzo di carte non ordinato possiamo ordinarlo scorrendo le carte una alla volta e inserendo ogni carta immediatamente dopo la carta più piccola tra quelle che la precedono. Osserviamo però che in questo caso le k schede già ordinate non sono ancora al loro posto definitivo, come accadeva nei due casi precedenti. Solo al termine della procedura esse acquisteranno tutte la loro giusta posizione. Programmazione Mod A - Cap 6 - prof. Burattini
Tutti ordinati Non ancora ordinati 61 65 63 11 33 UltimoElemento vet[1] vet[PostoSuccessivo] Inserisci tra questi due elementi Algoritmo Supponiamo di essere al passo j. Confrontiamo il valore dell’elemento di vet[j] con i suoi predecessori. Se chi lo precede ha un valore più elevato lo spostiamo di un posto in avanti. Se incontriamo nella posizione i un valore più basso allora poniamo in vet[i+1] vet[j]. Programmazione Mod A - Cap 6 - prof. Burattini
Poiché il primo elemento è sicuramente parzialmente ordinato, il for esterno può iniziare da 1. Al termine si uscirà dal loop allorché tutti gli N elementi sono parzialmente (e quindi definitivamente) ordinati. Prima che inizi il ciclo interno conserviamo il valore di vet[k] in vet[N], il posto k ora è ‘libero’ e può essere sfruttato per spostare verso destra ogni elemento già parzialmente ordinato, a partire dall’ultimo che ha indice k-1, che risulti maggiore di vet[N]. In definitiva avremo: for ( k=1;k<= N-1; k++) vet[N]vet[k] j k - 1 while ( j>=0)and (vet[j]>vet[N]) vet[j+1] vet[j] jj-1 vet[j+1]vet[N] In uscita dal loop interno sappiamo che in vet[j] si trova il più grande dei numeri più piccoli di vet[0] e dunque possiamo terminare il loop interno sistemando vet[N] nella posizione libera j+1. Naturalmente è possibile adoperare questo algoritmo solo se N non rappresenta la dimensione fisica dell’array a run time. Programmazione Mod A - Cap 6 - prof. Burattini
k [0] [1] [2] [3] [4] [5] [6] [7] 10 9 30 18 19 29 12 19 2 [0] [1] [2] [3] [4] [5] [6] [7] 10 9 30 18 9 29 12 19 3 10 19 30 18 9 29 12 9 19 30 18 9 29 12 10 9 [0] [1] [2] [3] [4] [5] [6] [7] 9 19 30 118 30 29 12 10 4 [0] [1] [2] [3] [4] [5] [6] [7] 9 19 30 18 29 29 12 10 5 19 29 18 29 30 12 9 10 j j j j Programmazione Mod A - Cap 6 - prof. Burattini
[0] [1] [2] [3] [4] [5] [6] [7] 9 19 29 18 12 30 12 10 19 29 18 12 12 30 9 10 19 12 18 12 29 30 9 10 12 19 18 12 29 30 9 10 [0] [1] [2] [3] [4] [5] [6] [7] 12 19 18 18 29 30 9 10 7 12 19 30 18 29 18 9 10 12 19 30 18 18 29 9 10 12 18 30 18 19 29 9 10 k j 6 j N° confronti: (n-1)+(n-2)+…+1=(n-1)*n/2 Programmazione Mod A - Cap 6 - prof. Burattini eserbuble
Se dobbiamo leggere da un file o da tastiera una successione di elementi che deve essere ordinata, potremmo dapprima inserirli in un array e poi ordinarli, ma in genere è preferibile eseguire le due operazioni contemporaneamente adoperando la tecnica dell’insertion sort. Si ottiene il seguente algoritmo: int main () { char ch; int a[100], elemento,j,N; cout<<" Fine inserimento= 0"<<endl; cout<<" Elemento "; cin>>elemento; a[0]=elemento; N=-1; while (elemento!=0) { cout<<" Elemento "; cin>>elemento; N=N+1; j=N; while ((j>=0) && (a[j]>elemento)) { a[j+1]=a[j]; j=j-1; a[j+1]=elemento; } } StampaVettore(a, N+1,'a'); system("pause"); return 0; } esersorttast Programmazione Mod A - Cap 6 - prof. Burattini
Al termina del loop N indica il numero di elementi letti. Naturalmente questo algoritmo funziona se il numero di elementi da leggere è inferiore alla dimensione fisica del vettore, altrimenti occorrerà un opportuno test su N prima di entrare nel loop interno. I tre algoritmi di ordinamento illustrati prevedono un numero di operazioni, scambi o confronti, all’incirca proporzionale al quadrato del numero N di elementi da ordinare. Dunque per ordinare un vettore di mille elementi occorrono circa un milione di operazioni. Programmazione Mod A - Cap 6 - prof. Burattini
ESERCIZI 1. Scrivere una procedura per l’algoritmo di Insertion-Sort. In seguito, utilizzando la libreria sui vettori, scrivere un driver per l’algoritmo. 2. Leggere ed ordinare una sequenza di interi letti da tastiera (uno zero indicherà che la sequenza è terminata). Programmazione Mod A - Cap 6 - prof. Burattini
Ricerca lineare Un problema molto comune è la ricerca di un elemento in un insieme. Nel caso di una variabile array, l’algoritmo di ricerca deve dire se un certo valore appartiene o no all’array. A questo scopo, detto A l’array ed x l’elemento da cercare, si esaminano sistematicamente tutti gli elementi dell’array per trovare un valore i dell’indice che soddisfa la condizione A[i] =x. Se, invece, x non appartiene all’array si restituisce, ad esempio, il valore -1. Si tratta dunque di un tipico algoritmo “esiste”. L’algoritmo di ricerca lineare è : i0 trovatofalse while NOT trovato AND i < N if A[i]=x trovatotrue else i=i+1 if trovato indice=i else indice=-1 Programmazione Mod A - Cap 6 - prof. Burattini
Possiamo eliminare la variabile sentinella trovato in questo modo: Scorriamo il vettore con un ciclo while controllato da una espressione booleana che termina il ciclo o quando A[i] = x, oppure quando arriva alla fine del vettore (si noti che questo si ottiene con un AND!!) ESERCIZIO Scrivere una function che implementi questo algoritmo qualunque sia il tipo di numero contenuto nell’array (int, float, double). i0 while A[i]<>x AND i < =N i=i+1 ; if A[i]=x indice=i else indice=-1 Programmazione Mod A - Cap 6 - prof. Burattini
L’algoritmo di ricerca lineare può essere migliorato se si hanno delle informazioni opportune sul tipo di array da esaminare. Ad esempio l’algoritmo di ricerca potrebbe essere migliorato se è noto che il vettore pur essendo disordinato presenta solo numeri negativi fino alla posizione k seguiti da valori non negativi . Infatti in questo caso se il numero da cercare non è negativo possiamo scartare i primi k+1 elementi. In altri termini ogni informazione che ci permette di scartare potenziali candidati è utile per migliorare la ricerca. Ricerca binaria Programmazione Mod A - Cap 6 - prof. Burattini
Cosa si può fare se il nostro array è ordinato? Si potrebbe adoperare una ricerca lineare modificata nel senso che o l’algoritmo si arresta non appena trova l’elemento in questione o si interrompe dando in uscita –1 non appena incontra un numero maggiore. Si avrebbe un certo miglioramento in media, ma nel caso peggiore occorre comunque esaminare tutto l’array. i0 while A[i]<x AND i < =N i=i+1 ; if A[i]=x indice=i else indice=-1 Programmazione Mod A - Cap 6 - prof. Burattini
Che informazione otteniamo se confrontiamo il nostro x con un generico elemento di indice k? Se x=A[k] la ricerca è finita, se è maggiore allora possiamo scartare tutti i candidati da 0 fino a k, altrimenti scartiamo tutti quelli da k in poi. Conviene scegliere k =n/2, in tal modo un confronto fallito dimezza il numero di possibili candidati. Iterando questo procedimento con cui dimezziamo l’indice e confrontiamo i valori, ad ogni fallimento i due estremi dell’intervallo di ricerca che contiene i candidati ancora non scartati si avvicinano sempre di più. L’algoritmo terminerà in una delle seguenti situazioni : a) uno dei confronti ha successo. b) gli estremi dell’intervallo di ricerca danno un intervallo vuoto. Nel qual caso l’elemento non è nell’array. Programmazione Mod A - Cap 6 - prof. Burattini
Lo pseudocodice dell’algoritmo viene proposto di seguito. basso 0 Alto N-1 i -1 while (basso<=Alto)and (i=-1) Medio = (basso+Alto) / 2 if x = vet[Medio] i=Medio else if x>vet[Medio] basso = Medio+1 else Alto =Medio-1 Programmazione Mod A - Cap 6 - prof. Burattini
[0] [1] [2] [3] [4] [5] [6] [7] 21 29 30 9 10 15 18 35 1 [4] [5] [6] [7] 21 29 30 35 2 [4] [5] 21 29 3 [4] 4 21 N O(N) LOG(N) 1.000 1.000 9,97 1.000.000 1.000.000 19,93 100.000.000 100.000.000 26,58 Vogliamo sapere se 21 appartiene alla seguente lista vet=[ 9, 10, 15, 18, 21, 29, 30, 35 ] di dimensione 8. N N/2 N/4 1 N/20 N/21 N/22 N/2k k=log2N Programmazione Mod A - Cap 6 - prof. Burattini
Utilizzando l’algoritmo , vogliamo verificare se 21 appartiene al vettore di interi: vet=[ 9, 10, 15, 18, 21, 29, 30, 35 ] di dimensione 8. Nel nostro esempio x=21, basso=0 ed Alto=7. Inizialmente Medio=(0+7)/2=3, per cui, essendo vet[3]=18, si ha x > vet[medio] è vero analizziamo il sub-array superiore che va dall’indice 4 fino ad Alto; per questo scopo basta porre basso=Medio+1=4. Abbiamo basso=4, Alto =7 Medio=(4+7)/2=5 e vet[Medio]=29. Dal confronto x > vet[medio] falso scaturisce che dobbiamo analizzare il subarray inferiore (da 5 a 4), per cui Alto=Medio-1=6; poiché basso=4, Alto=6 e Medio=(4+6)/2=5 si ottiene ancora x > vet[medio] falso per cui vale Alto=Medio-1=5, basso=4, Medio=(4+5)/2=4 ed infine vet[Medio]=19 e l’algoritmo restituisce l’indice del valore cercato, i=4. 0 1 2 3 4 5 6 7 basso 0 Alto N-1 i -1 while (basso<=Alto)and (i=-1) Medio = (basso+Alto) / 2 if x = vet[Medio] i=Medio else if x>vet[Medio] basso = Medio+1 else Alto =Medio-1 Programmazione Mod A - Cap 6 - prof. Burattini
vet=[ 9, 10, 15, 18, 21, 29, 30, 35 ] Analizziamo la ricerca con x=17. Scrivendo i vari passaggi in maniera più compatta, otteniamo basso Alto Medio x =vet[Medio] x > vet[Medio] 0 7 3 falso falso 0 2 1 falso vero 1 2 2 falso vero 2 2 2 falso vero 3 2 poiché basso è maggiore di Alto non esiste più alcun intervallo di ricerca. 0 1 2 3 4 5 6 7 Programmazione Mod A - Cap 6 - prof. Burattini
Se applicato ad un array ordinato in cui sono possibili ripetizioni l’algoritmo termina con successo dando uno dei possibili indici per cui l’uguaglianza risulta verificata. E’ possibile trovare il più piccolo indice per cui l’uguaglianza è verificata eliminando il test su i. Il loop si riduce a: basso 0 Alto N-1 while (basso<=Alto) Medio (basso+Alto) / 2 if x > vet[Medio] basso Medio+1 else Alto Medio-1 Osserviamo che allorché x<= vet[Medio] noi modifichiamo Alto Programmazione Mod A - Cap 6 - prof. Burattini
Nel caso sia vera la condizione x > vet[Medio] allora possiamo affermare che la ricerca va effettuata nel sub-array superiore e che in uscita dal loop si avrà: x > vet[basso-1] (poiché basso-1=Medio in uscita) inoltre tale condizione resta vera anche quando basso non viene modificato, visto che l’elemento basso-1 è stato escluso dai possibili candidati Se, invece, è vera la condizione x <= vet[Medio] allora la ricerca va effettuata nel sub-array inferiore; inoltre, risulta verificata la condizione x <= vet[Alto + 1] (poiché Alto+1=Medio in uscita), condizione ovviamente soddisfatta se Alto non viene alterato. Dunque qualunque strada si prende nel loop è sempre vero che in uscita si ha: Vet[basso-1] < x <= vet[Alto + 1] Il ciclo termina con la negazione di (basso <= Alto), cioè con basso > Alto Programmazione Mod A - Cap 6 - prof. Burattini
Analizzando gli esempi, possiamo verificare che all’uscita si ha basso = Alto + 1 Se in un certo punto del programma risulta che vet[Medio] coincide col valore cercato x; nell’algoritmo precedente si esce dal ciclo. In questo caso l’algoritmo continua e, poiché siamo nella situazione che segue l’else, avremo Alto= Medio –1; da cui Medio = Alto + 1 Quindi il valore cercato è conservato nell’indice Alto + 1. Poiché l’intervallo con cui proseguire la ricerca è [basso, alto], se gli elementi sono tutti distinti, le ricerche successive non cambieranno mai il valore di Alto, essendo tali elementi più piccoli dell’elemento cercato; alla fine il ciclo terminerà con l’uguaglianza basso = Alto + 1 e quindi l’elemento cercato sarà posizionato nell’indice contenuto nella variabile basso. Programmazione Mod A - Cap 6 - prof. Burattini
Nel caso in cui vi siano più elementi uguali, l’algoritmo troverà altri indici compresi nell’intervallo [basso, alto] che contengono il valore x cercato. Se applichiamo ancora il ragionamento precedente è chiaro che l’algoritmo determinerà il primo indice in cui appare x. Cosa accade nel caso in cui l’elemento cercato x non esiste nell’array? Poiché l’algoritmo termina in ogni caso con basso = Alto +1 dobbiamo distinguere il caso in cui l’indice basso<=N-1 dal caso particolare in cui basso=N che si verifica se l’elemento cercato è più grande di tutti gli elementi dell’array. Occorre quindi aggiungere al termine del loop il seguente test: If (basso=N) or not(vett[basso]=x) Indice= -1 else indice = Basso Programmazione Mod A - Cap 6 - prof. Burattini
Ecco un programma che utilizza le due ricerche binarie sotto la forma di functions; esse restituiscono un intero che rappresenta l’indice dell’elemento cercato. La function RicercaBinB rappresenta la ricerca con la variabile booleana, RicercaBin invece nonutilizza tale variabile. do { cout<<"Valore da cercare="; cin>>cerca; if ((RicercaBinB(a,0,n,cerca)>=0)||(RicercaBin(a,0,n,cerca)>=0)) { cout<<"Il valore "<<cerca<<" ha la posizione="<<RicercaBinB(a,0,n,cerca)<<endl; cout<<"Senza Flag, il valore "<<cerca<<" ha la posizione="<<RicercaBin(a,0,n,cerca)<<endl; } else cout<<"Il valore "<<cerca<<" non e' nel vettore"<<endl; cout<<" f per terminare "; cin>>ch; } while (ch!='f'); return 0; } #include <iostream> #include <cstdlib> #include "InsertArray.h" using namespace std; int RicercaBinB (int[], int, int, int); int RicercaBin (int[], int, int, int); void ordinaB(int[], int n); void scambia (int&, int&); int main () { char ch; int a[100], n, cerca; cout<<" Lunghezza vettore="; cin>>n; LeggeVettore ( a, n, 'a'); ordinaB (a,n); StampaVettore (a, n,'a'); void scambia (int &x1, int &x2) { int s; s=x1; x1=x2; x2=s; } Programmazione Mod A - Cap 6 - prof. Burattini
void ordinaB ( int vet[], int N) { int j, k; for (k=0; k<N-1; k++) for (j=k+1; j<N; j++) if (vet[k] > vet[j]) scambia (vet[k],vet[j]); } int RicercaBinB ( int vet[], int basso, int alto, int x) { int medio,i=-1; while ((basso<=alto) && i==-1) { medio=(basso+alto)/2; if (vet[medio]==x) i=medio ; else if (vet[medio]<x) basso=medio+1; else alto=medio-1; } return i; } int RicercaBin ( int vet[], int basso, int alto, int x) { int medio, Ntot=alto; while (basso<=alto) { medio=(basso+alto)/2; if (vet[medio]<x) basso=medio+1; else alto=medio-1; } if (( basso==Ntot) || (vet[basso]!=x)) return -1; else return basso; } Programmazione Mod A - Cap 6 - prof. Burattini
s [i] Restituisce il carattere di indice i (se i>= della lunghezza della stringa, il risultato è indefinito s.size ( ) Restituisce la lunghezza di s s.empty ( ) Restituisce true se s è vuota, false altrimenti s.find( c ) Restituisce l’indice della prima occorrenza di c s.find (str) Restituisce l’indice del primo carattere della prima occorrenza di str s.rfind ( c ) Come s.find( c ), solo che la ricerca ha inizio dalla fine s.rfind (str) Come s.find(str), solo che la ricerca ha inizio dalla fine s.replace (i, n, str) Sostituisce n caratteri, a partire dalla posizione i, con la stringa str. s.insert (i, str) Inserisce la stringa str a partire dalla posizione i s.erase (i, n) Elimina n caratteri a partire dalla posizione i s.resize (n,car) Fissa a n la lunghezza di s; gli altri caratteri fino alla lunghezza della stringa sono riempiti con il carattere car s.c_str ( ) Restituisce la stringa corrispondente in stile C s.substr (i,n) Restituisce una stringa che parte dalla posizione i ed ha lunghezza n; per esempio se s=”ciao mamma”, s.substr(5,5) restituisce la stringa “mamma” Programmazione Mod A - Cap 6 - prof. Burattini
/* DATA UNA STRINGA E UN NUMERO K MOSTRARE A VIDEO TUTTE LE K-PLE UGUALI ALLA K-PLA SUCCESSIVA . ES. K=3 A=SBFGBJGBJNOGDFRDFR OUTPUT GBJDFR*/ // DEFINIZIONI void leggi_dati(char r1[]) { cout<<" Dammi la stringa "; cin>>r1; } bool controlla(string sx, string sy, int k1) { int j=0; bool uguale=false; while ((j<=k1) && (sx[j]==sy[j])) j++; if ((j-1)==k1) uguale=true; return uguale; } void cerca_kple(string s1, int k1) { int j=0; while (j<(s1.size()-k1-1)) { if (controlla(s1.substr(j,k1),s1.substr(j+k1,k1),k1)==true) cout<<" trovato "<<s1.substr(j,k1)<<endl; j=j+k1; } } #include <iostream> #include <cstdlib> #include <string> using namespace std; // PROTOTIPI void leggi_dati(char[]); void cerca_kple(string,int); bool controlla(string,string,int); // MAIN int main () { string s; char rigo[120]; int k; leggi_dati(rigo); s=rigo; cout<<"\n Dammi k "; cin>>k; cerca_kple(s,k); system("pause"); } Programmazione Mod A - Cap 6 - prof. Burattini
Esercizio Data una stringa S, eliminare la sottostringa centrale di dimensioni k. Se la stringa rimanente è strettamente palindroma allora restituire la stringa vuota. Esempio: S=abcdfghtrdcba , k=5 eliminata fghtr resta abcddcba che è palindroma. Pseudo codice Leggi s e k Controlla coerenza s e k Cancella da s la sottostringa centrale di ampiezza k Controlla se la stringa rimanente è palindroma(s) Stampa il risultato Palindroma(s) lung=s.size() while lung>0 AND s[0]=s[lung-1] { s.erase (lung-1, 1) s-erase (0,1) lung=s.size() } return (s.empty()) Programmazione Mod A - Cap 6 - prof. Burattini
/* Data una stringa S di lunghezza pari (dispari), eliminare la sottostringa centrale di dimensioni k con k pari (dispari). Se la stringa rimanente è strettamente palindroma allora restituire la stringa vuota. */ #include <iostream> #include <cstdlib> #include <string> using namespace std; // PROTOTIPI void leggi_dati(char[]); bool palindroma(string); // MAIN int main () { int k; string s; char rigo[120]; leggi_dati(rigo); s=rigo; cout<<"\n Dammi k "; cin>>k; if ((s.size()%2)!= (k%2)) { cout<<" Lunghezza stringa e valore di k non coerenti"<<endl; return -1; } s.erase((s.size()-k)/2,k); if (palindroma(s)) cout<<" La stringa e‘ palindroma "<<endl; else cout<<" La stringa non e‘ palindroma"<<endl; } // DEFINIZIONI void leggi_dati(char r1[]) { cout<<" Dammi la stringa "; cin>>r1; } bool palindroma(string s1) { int lung; lung=s1.size(); while (((lung>0)) && (s1[0]==s1[lung-1])) { s1.erase (lung-1, 1); s1.erase (0, 1); lung=s1.size(); } return (s1.empty()); } eserSTRING2c Programmazione Mod A - Cap 6 - prof. Burattini
Array bidimensionali Un array multidimensionale è un array definito in modo tale che per poter accedere ad un suo elemento sono necessari più indici. In particolare, un array definito in termini di due indici è detto array bidimensionale o matrice. Esempi di dichiarazione di una matrice: int C[4][3]; // dichiara una matrice di interi con quattro righe e tre colonne float f[M][N]; // dichiara una matrice di reali con M righe ed N colonne: a runtime i valori di M ed N devono essere noti int A[ ][3]= { 1,2,3,4,5,6,7,8,9 }; // specifica una matrice con 9 elementi: il compilatore ne deduce che la matrice ha anche 3 righe, quindi come se la dichiarazione fosse A[3][3] char b[2][3]={{‘a’, ’b’, ’c’},{‘d’, ‘e’, ‘f’}} Programmazione Mod A - Cap 6 - prof. Burattini
colonne Colonna 0 Colonna 1 Colonna 2 righe Riga 0 C[0][0] C[0][1] C[0][2] Riga 1 C[1][0] C[1][1] C[1][2] Riga 2 C[2][0] C[2][1] C[2][2] Riga 3 C[3][0] C[3][1] C[3][2] L’array bidimensionale C può essere rappresentato nella seguente forma tabellare: Programmazione Mod A - Cap 6 - prof. Burattini
colonne Colonna 0 Colonna 1 Colonna 2 righe Riga 0 3 -5 7 Riga 1 4 8 -1 Riga 2 0 2 6 Riga 3 9 1 -6 Ogni elemento viene scritto utilizzando due coppie di parentesi quadre: la prima coppia di parentesi contiene l’indice della riga, la seconda coppia l’indice della colonna. Se inseriamo nella matrice C dei valori interi otteniamo la seguente rappresentazione: In questo caso abbiamo, per esempio C[0][0]=3 ; C[2][1]=0 ; C[3][2]=1. Programmazione Mod A - Cap 6 - prof. Burattini
Esempio. Una classe composta da 32 studenti ha sostenuto durante l’anno 5 compiti in classe. Supponiamo di voler scrivere un programma che calcoli la media dei voti ottenuti dagli studenti . Si potrebbe allora dichiarare una matrice del tipo: int A[31][7] in cui inserire i voti riportati da ciascun studente in ciascun compito. Siccome però in una classe ci potrebbero essere più studenti o i compiti potrebbero essere di più, conviene adoperare per maggior generalità la seguente dichiarazione: int const R=40; int const C=8; int A[R][C]; int n=30, m=4. Adotteremo la convenzione che il valore 0 indicherà un compito non consegnato perché lo studente era assente quel giorno. Una volta inseriti i voti di ciascun studente la matrice sarà del tipo: Programmazione Mod A - Cap 6 - prof. Burattini