I Vettori sono delle
Strutture Dati
utilizzabili nei
Linguaggi di Programmazione evoluti. Una
Struttura Dati è uno
strumento Concettuale utile per memorizzare Informazioni secondo una certa logica e
disposizione. Nel Vettore si possono memorizzare più informazioni dello stesso tipo in
adiacenza fisica, e cioè una vicina all'altra. Il vettore è formato da
Elementi in cui sono memorizzate le informazioni, una per ogni
elemento, e si può considerare come una variabile multipla.
Ad ogni Vettore viene sempre
associato un Nome Simbolico
- come per le variabili semplici
- e per distinguere i vari elementi fra di loro viene utilizzato un
Indice. L'Indice
è
sostanzialmente un numero intero rappresentato da una costante, da una variabile o da
un'espressione, che segue, fra parentesi quadre in Pascal, tonde in Basic, il Nome del
Vettore. Normalmente il primo elemento di un Vettore è identificato da un valore di
Indice pari ad 1, il secondo da 2, il terzo da tre ecc.
Di seguito viene riportato un esempio di definizione di Vettore in Pascal e uno in Basic:
Var
Numeri : Array[1 .. 100] of Integer;
La dichiarazione precedente,
in Pascal, serve per definire un Vettore di 100 elementi in cui il primo elemento
viene identificato da un valore di Indice pari ad 1. Il nome del Vettore è Numeri.
Per impostare nel terzo elemento di Numeri un certo valore, ad esempio 10, si può
utilizzare l'assegnazione seguente:
Numeri[3] := 10;
oppure
I := 3;
Numeri[I] := 10;
In Basic lo stesso Vettore lo si può definire in questo modo:
Dim Numeri( 1 to 100) as Integer
o anche con
Dim Numeri(99) as Integer
in quest'ultimo caso il primo elemento sarà identificato da un valore di Indice pari a 0.
Come si è visto occorre
definire il numero massimo di elementi utilizzabili per il vettore.
Normalmente si usano gli elementi, a partire dal primo, in sequenza, senza
lasciare vuoti. Cercare di utilizzare un elemento con un indice superiore al valore di indice
massimo provoca un errore in fase di esecuzione, con interruzione del programma.
Per ricordare quanti elementi sono stati
effettivamente impostati in un vettore, si utilizza una variabile intera in cui si
memorizza il valore di indice dell'ultimo elemento impostato.
Il Vettore permette di memorizzare insiemi di valori utilizzando un unico nome simbolico. Con i cicli, facendo variare il valore dell'indice, è possibile operare su tutti gli elementi di un vettore. Come esempio viene riportato un Flow in cui, mediante un ciclo While, vengono visualizzati i primi N valori presenti in un vettore di nome Vet (viene utilizzata la variabile I come indice del vettore):
In Pascal:
-----------------
I := 1;
While I <= N do
begin
Writeln(Vet[I]);
I := I + 1;
end;
Il ciclo For poteva, in
questo caso,
essere convenientemente utilizzato al posto del ciclo While.
Il ciclo For è utilissimo per operare sui vettori. La variabile di controllo
del ciclo For può
anche servire come indice del vettore per indicare, ad ogni ripetizione, un
suo elemento
diverso.
In Pascal
-------------
For I := 1 to N do
Writeln(Vet[I]);
Per impostare più valori in un vettore, a partire dal primo elemento, si possono utilizzare due strategie:
1) Impostare in Input il numero degli elementi da inserire, e successivamente inserire all'interno di un ciclo For gli elementi, uno alla volta:
In Pascal
Program Carica1;
Uses Wincrt;
Var
Vet: Array[1..100] of integer;
I,N:integer;
begin
Writeln(' Quanti elementi da inserire ?
');
Readln(N);
For I := 1 to N do
begin
Writeln(' Inserire l''elemento n. ',I);
Readln(Vet[I]);
end;
-------------
end.
2) Inserire un elemento alla volta chiedendo all' operatore se c'è un altro elemento da inserire:
In Pascal
Program Carica2;
Uses Wincrt;
Var
Vet:Array[1..100] of integer;
N:integer;
Risp:char;
begin
N := 0;
Repeat
N := N + 1;
Writeln('Inserire il valore n. ',N);
Readln(Vet[N);
Write('Vuoi continuare ? (S/N) -> ');
Readln(Risp);
Until (Risp = 'N') or (Risp = 'n');
----------------
end.
Le due strategie portano allo stesso risultato, ovviamente la prima prevede che vengano contati a priori i valori da inserire ed è comoda quando gli elementi del vettore sono pochi, o quando si sa con precisione quanti sono; la seconda ha come onere, da parte dell'operatore, la risposta alla domanda "Vuoi continuare ? (s/n)", ma non prevede che vengano contati, a priori, i valori da inserire. Si sceglierà, quindi, il metodo più conveniente, a seconda delle esigenze.
Vediamo ora come si può ricercare un
valore specifico all'interno di un vettore precedentemente impostato.
Esistono sostanzialmente tre metodi:
RICERCA SERIALE (non prevede che i valori siano in una sequenza crescente) |
|
RICERCA SEQUENZIALE (prevede che i valori siano in una sequenza crescente) |
|
RICERCA DICOTOMICA (prevede che i valori siano in una sequenza crescente) |
Vediamo ora la RICERCA SERIALE:
I valori utili sono stati impostati
nel vettore VET a partire dal primo elemento, senza lasciare elementi vuoti. La variabile
di comodo N sarà stata impostata con un valore numerico intero, ad indicare quanti valori
sono stati impostati nel vettore (VET e N sono due nomi simbolici utilizzati per spiegare
il procedimento).
La ricerca di uno specifico valore, con il metodo seriale, prevede che venga preso in
considerazione il valore presente nel primo elemento del vettore e via via gli altri
valori negli elementi sucessivi, ovviamente uno alla volta. La ricerca terminerà con
esito positivo se il valore cercato verrà trovato, o con esito negativo se, dopo aver
preso in considerazione gli N elementi del vettore, non si sarà trovato alcun valore
corrispondente a quello cercato.
Il numero di elementi che verranno presi in considerazione (si possono anche equiparare ai
numeri di passi necessari) in caso di esito negativo, cioè per non
trovato, saranno N, mentre in caso di
esito positivo, cioè per trovato, saranno in
media N/2, poichè l'elemento cercato, se presente,
può trovarsi ovunque nel vettore.
La variabile Flag è una variabile di comodo che serve per uscire dal ciclo While non appena viene individuato il valore cercato. La stessa variabile servirà come indicatore del fatto che il valore è stato trovato (valore 1 impostato nel ramo "vero" del confronto X = Vet(I))
In Pascal
Writeln('Inserire il
valore da cercare');
Readln(X);
I := 0;
Flag := 0;
While (Flag=0) And (I<=N) do
if (X = Vet[I]) then
Flag := 1
else
I := I + 1;
if Flag = 1 then
Writeln('Trovato')
else
Writeln('NON Trovato');
Vediamo ora la RICERCA SEQUENZIALE:
La ricerca sequenziale è molto
simile alla ricerca seriale e si differenzia da questa solo per il fatto che, essendo i
valori nel vettore in ordine crescente, il confronto con gli elementi può anche terminare
non appena viene individuato un valore più grande di quello che si cerca. L'ordinamento
crescente prevede che sia vera questa situazione: Vet(1) <= Vet(2) <= Vet(3) <=
...... <= Vet(N). Dopo aver individuato un elemento più grande di quello che si
cerca, si è nella situazione di non dovere più esaminare i successivi elementi, tutti
più grandi ancora.
Il numero di passi per trovato non cambia ed è
sempre N/2; cambia invece il numero di passi per
non trovato, che si può ritenere, in media, pari a N/2.
Questo perchè non è necessario esaminare tutti
gli elementi (normalmente) per essere certi della inesistenza del valore cercato.
In Pascal
Writeln('Inserire il
valore da cercare');
Readln(X);
I := 0;
Flag := 0;
While (Flag=0) And (I<=N) do
if (X = Vet[I]) then
Flag := 1
else
if (Vet[I]
> X) then
Flag := 2
else
I := I + 1;
if Flag = 1 then
Writeln('Trovato')
else
Writeln('NON Trovato');
Vediamo ora la RICERCA DICOTOMICA:
Dicotomia è una parola che deriva dal Greco antico e indica una separazione, in due parti, di un qualche oggetto o cosa. In informatica " Ricerca Dicotomica" indica un procedimento che serve per individuare un valore in un insieme ordinato (nel nostro caso, al momento, un vettore) procedendo per esclusione di metà degli elementi: la prima parte dell'insieme, o la seconda parte, a seconda che il valore da cercare sia minore di quello presente a metà dell'insieme, oppure sia maggiore. Si procederà, nuovamente per esclusione, con la parte di insieme individuato nel passaggio precedente, riducendo nuovamente, con lo stesso procedimento, gli elementi in cui cercare. La ricerca terminerà, per trovato, se verrà individuato il valore cercato in uno dei confronti operati per individuare la parte di insieme in cui cercare (prima di confrontare per maggiore si confronterà per uguale), o per non trovato se l'insieme in cui cercare si sarà ridotto ad un elemento, e poi a nessun elemento. Il numero di passi necessari per individuare un valore con questo procedimento non segue più una legge lineare, come per i due metodi precedentemente presentati, ma la legge seguita è di tipo logaritmico. Infatti se i valori sono N, dopo un passo si ridurranno di N/2, dopo due passi di N/4 ... ; quando il numero di elementi rimasti si ridurrà a 1, la ricerca terminerà per non trovato, oppure per trovato nella peggiore ipotesi. Il numero di passi sarà, quindi, quante volte abbiamo dovuto dividere l'insieme di ricerca per ottenere un unico valore. Questo numero è, per definizione matematica, il Logaritmo in base due di N, e cioè quel numero che messo come esponente a due permette di ottenere N. Se gli elementi in cui cercare sono, ad esempio, 1024 dopo un passo si ridurranno a 512, dopo 2 passi a 256, dopo 3 a 128 ... dopo 10 a 1.Dieci, nel caso precedente, è il numero di passi necessari per non trovato o per trovato nella peggiore delle ipotesi, ed è appunto il logaritmo in base 2 di 1024. La ricerca sequenziale o la seriale avrebbero richiesto N/2 passi o elementi e cioè circa 500 passi. Si può osservare come i numeri dicano quanto possa essere più veloce la ricerca di tipo dicotomico, specialmente quando gli elementi in cui cercare sono molti. Si può notare, inoltre, che raddoppiando gli elementi il numero di passi aumenta solo di uno. La ricerca dicotomica è in pratica quella che ognuno di noi, almeno in modo empirico, mette in atto quando cerca un nominativo in un elenco telefonico o quando cerca un termine in un dizionario. In Informatica questo tipo di ricerca assume un'importanza fondamentale, visto il ridottissimo numero di passi richiesto rispetto agli altri metodi. Ovviamente questo tipo di ricerca non può essere effettuata se i valori nell'insieme di ricerca non sono ordinati.
In Pascal
Writeln('Inserire il
valore da cercare');
Readln(X);
Inizio := 1;
Fine := N;
Flag := 0;
While (Inizio <= Fine) And (Flag = 0) do
begin
Med :=
(Inizio + Fine) Div 2;
if (X =
Vet[Med]) then
Flag := 1
else
if (X > Vet[Med]) then
Inizio := Med +1
else
Fine := Med - 1;
end;
if Flag = 1 then
Writeln('Trovato')
else
Writeln('NON Trovato');