Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(appunti): [Anno1] Programmazione orientata agli oggetti #75

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
Il Bubblesort è un algoritmo per mettere in ordine array non ordinati.
È chiamato cosi dato che nel suo funzionamento ricorda delle bolle che si scambiano.

static public void ordina(int v[]){
int temp;
for(int i = 0; i<v.length - 1; i++){ //N-1 passi
for(int j = v.length - 1; j>i; j--){ //N-(i+1) passi
if(v[j]<v[j-1]){ //confronto
temp = v[j];
v[j] = v[j-1]; //o 0 o 3 assegnamenti
v[j-1] = temp;
}
}
}
}
Comment on lines +4 to +15
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static public void ordina(int v[]){
int temp;
for(int i = 0; i<v.length - 1; i++){ //N-1 passi
for(int j = v.length - 1; j>i; j--){ //N-(i+1) passi
if(v[j]<v[j-1]){ //confronto
temp = v[j];
v[j] = v[j-1]; //o 0 o 3 assegnamenti
v[j-1] = temp;
}
}
}
}
```java
static public void ordina(int v[]){
int temp;
for(int i = 0; i<v.length - 1; i++){ //N-1 passi
for(int j = v.length - 1; j>i; j--){ //N-(i+1) passi
if(v[j]<v[j-1]){ //confronto
temp = v[j];
v[j] = v[j-1]; //o 0 o 3 assegnamenti
v[j-1] = temp;
}
}
}
}


il suo funzionamento è abbastanza semplice

>considerando un vettore non ordinato partiamo dal fondo ed considerando a coppie i numeri li confrontiamo per vedere chi è il valore più grande che deve stare sempre a destra della coppia.
>
>Es
>`3 1 5 9 (7 2)`
>partiamo dal fondo quindi e ci chiediamo `7<2` ? se è vero lasciamo tutto com'è ma dato che è falso li scambiamo di posto.
>
>`3 1 5 (9 2) 7`
>analogamente, `9<2`? no perciò scambiamo.
>
>`3 1 (5 2) 9 7`
>`5<2`? no perciò scambiamo.
>
>`3 (1 2) 5 9 7`
>`1<2`? si in questo caso le cose si lasciano cosi come sono.
>
>`(3 1) 2 5 9 7`
>`3<1`? no perciò scambiamo.
>
>`1 3 2 5 9 7` è qui finisce la prima iterazione.
>
>Ora dato che l'elemento più piccolo è al suo posto non c'è più bisogno di confrontarlo e tantomeno spostarlo.
>Dunque la seonda iterazione sarà:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
>Dunque la seonda iterazione sarà:
>Dunque la seconda iterazione sarà:

>
>`1 | 3 2 5 (9 7)`
>`9<7`? no perciò scambiamo
>
>`1 | 3 2 (5 7) 9`
>`5<7`? si perciò non facciamo nulla
>
>`1 | 3 (2 5) 7 9`
>`2<5`? si perciò non facciamo nulla
>
>`1 | (3 2) 5 7 9`
>`3<2`? no perciò scambiamo
>
>`1 | 2 3 5 7 9` ed qui finisce la seconda iterazione
>ora dato il secondo elemento più piccolo è al suo posto nella terza iterazione non lo dobbiamo considerare perciò
>
>`1 2 | 3 5 7 9` ed cosi via...

Andando ad analizzare la complessità abbiamo che :

>_La complessità spaziale:_ è costante si tratta di 3 interi e un riferimento quindi non abbiamo molto spazio occupato.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non capisco bene il concetto di questa frase 🤔 Perchè 3 interi ?
L'idea che volevi esprimere era una roba del tipo: "Dato che non è stata utilizzata nessuna struttura ausiliaria durante l'esecuzione di questo algoritmo la complessità spaziale è considerabile costante" ?


Considerando la lunghezza del vettore come $N$.

>Abbiamo due cicli che sono uno dentro l'altro.
>- Il ciclo esterno viene eseguito $N-1$ volte.
>- Quello più interno $N-1-i$.

Contando il numero di operazioni. Per ogni iterazione del ciclo `for` più esterno vengono eseguiti $N-1-i$ confronti nel ciclo più interno. In totale ne vengono eseguiti :

$$(N-1)+(N-2)+...+1 = \frac{N(N-1)}{2}$$
Per quanto riguarda gli assegnamenti, nel caso migliore gli assegnamenti che non situati nel ciclo for più interno non vengono mai eseguiti perché l'argomento dell'`if` è falso.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Volevi scrivere sono invece che non ?

Suggested change
Per quanto riguarda gli assegnamenti, nel caso migliore gli assegnamenti che non situati nel ciclo for più interno non vengono mai eseguiti perché l'argomento dell'`if` è falso.
Per quanto riguarda gli assegnamenti, nel caso migliore gli assegnamenti che sono situati nel ciclo for più interno non vengono mai eseguiti perché l'argomento dell'`if` è falso.


Nel caso peggiore però in ogni iterazione del ciclo `for` interno vengono eseguiti $3$ assegnamenti, quindi in tutto ne vengono eseguiti

$$3(N-1)+3(N-2)+...+3 = \frac{3N(N-1)}{2}$$

****
**Riassumendo**
Il caso migliore (un vettore già ordinato)
$$\frac{N(N-1)}{2}\space\space\space confronti$$
Il caso peggiore (insieme inversamente ordinato)
$$\frac{N(N-1)}{2}\space\space confronti + \frac{3N(N-1)}{2}\space\space assegnamenti$$
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Complessità computazionale
Per poter misurare l'efficenza di un algoritmo a prescindere dalla tecnologia, consideriamo il tempo di esecuzione proporzionale al numero di operazioni che vengono effettuate dall'algoritmo.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Per poter misurare l'efficenza di un algoritmo a prescindere dalla tecnologia, consideriamo il tempo di esecuzione proporzionale al numero di operazioni che vengono effettuate dall'algoritmo.
Per poter misurare l'efficienza di un algoritmo a prescindere dalla tecnologia, consideriamo il tempo di esecuzione proporzionale al numero di operazioni che vengono effettuate dall'algoritmo.


>I problemi vengono classificati in differenti classi di complessità, in base all'efficenza.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
>I problemi vengono classificati in differenti classi di complessità, in base all'efficenza.
>I problemi vengono classificati in differenti classi di complessità, in base all'efficienza.


### Una misurazione dettagliata può essere difficilemente applicabile per questo si introducono delle approssimazioni.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Una misurazione dettagliata può essere difficilemente applicabile per questo si introducono delle approssimazioni.
### Una misurazione dettagliata può essere difficilmente applicabile per questo si introducono delle approssimazioni.


>In particolare si ricorre alla notazione $O(f(n))$.
>**def:**
>$$g(n) \in O(f(n)) \space se \space \exists(n_{0},c) \geq 0, \space n_{0} \geq 0 \space\space t.c.\space \forall n>n_{0}, \space g(n)\leq c\cdot f(n)$$

**Es:**
$$3n^2+5n+6 \in O(n^2)$$
Se prendo un vaolre di $c$ abbastanza grande
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Se prendo un vaolre di $c$ abbastanza grande
Se prendo un valore di $c$ abbastanza grande

$$3n^2+5n+6 < 4n^2$$
****

## Ordini
- costante
- $log(n)$
- $n$ (lineare)
- $n \cdot log(n)$
- $n^k$
- $2^n$
- $n!$

Sono in ordine dal più efficente al meno efficente
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Sono in ordine dal più efficente al meno efficente
Sono in ordine dal più efficiente al meno efficiente


***

## I dati di input
Le prestazioni di un algoritmo possono dipendono dall'input che gli viene fornito

ci sono tre casistiche:

#### Caso migliore
È il caso più favorevole al nostro algoritmo, *i dati richiedono meno elaborazione per essere trattati*

#### Caso peggiore
Prevede il numero massimo di passi per l'elaborazione dell'output

#### Caso medio
è il caso più utile da analizzare perché fornisce un reale indicatore della complessità dell'algoritmo.
Tendenzialmente è anche quello più complesso dato che spesso è difficile determinare quali sono i dati medi.
Per risolvere il problema del caso medio si preferisce eseguire molte simulazioni dell'algoritmo e poi dai tempi ottenuti con le simulazione estrarre una formula che approssimi adeguatamente l'andamento medio.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Per risolvere il problema del caso medio si preferisce eseguire molte simulazioni dell'algoritmo e poi dai tempi ottenuti con le simulazione estrarre una formula che approssimi adeguatamente l'andamento medio.
Per risolvere il problema del caso medio si preferisce eseguire molte simulazioni dell'algoritmo e poi dai tempi ottenuti con le simulazioni estrarre una formula che approssimi adeguatamente l'andamento medio.


***
## La santa trinità delle notazioni
- **O (big O – O grande):** indica il limite superiore della funzione asintotica e può essere considerata come la relazione matematica _minore o uguale_. Ad esempio, l’_iterazione_ di tutti gli elementi di un array di dimensione pari ad $N$, avrà un tempo di esecuzione pari a **O(N)**, poiché si ha la necessità di iterare tutti gli $N$ elementi. Il tempo di esecuzione dell’esempio precedente può essere indicato anche come **O(N²)**, oppure come **O(N³)**, poiché è certo che l’algoritmo avrà un tempo di esecuzione _minore_ _o uguale_ a questi valori.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **O (big O – O grande):** indica il limite superiore della funzione asintotica e può essere considerata come la relazione matematica _minore o uguale_. Ad esempio, l’_iterazione_ di tutti gli elementi di un array di dimensione pari ad $N$, avrà un tempo di esecuzione pari a **O(N)**, poiché si ha la necessità di iterare tutti gli $N$ elementi. Il tempo di esecuzione dell’esempio precedente può essere indicato anche come **O(N²)**, oppure come **O(N³)**, poiché è certo che l’algoritmo avrà un tempo di esecuzione _minore_ _o uguale_ a questi valori.
- **O (big O – O grande):** indica il limite superiore della funzione asintotica e può essere considerata come la relazione matematica _minore o uguale_. Ad esempio, l’_iterazione_ di tutti gli elementi di un array di dimensione pari ad $N$, avrà un tempo di esecuzione pari a **O(N)**, poiché si ha la necessità di iterare tutti gli $N$ elementi. Il tempo di esecuzione dell’esempio precedente può essere indicato anche come **O(N^2)**, oppure come **O(N^3)**, poiché è certo che l’algoritmo avrà un tempo di esecuzione _minore_ _o uguale_ a questi valori.


- **Ω (big Omega – Omega grande):** indica il limite inferiore della funzione asintotica e può essere considerata come la relazione matematica _maggiore o uguale_. Sempre in riferimento al tempo di esecuzione dell’esempio precedente, si indica come **Ω(N)** oppure **Ω(1)**, perché si è sicuri che l’algoritmo **non** possa essere **più veloce** di tale valore.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come mai non hai usato la rappresentazione matematica di Omega ($\Omega) ma hai usato il carattere ?
E' un problema legato ad obsidian ?


- **Θ (big Theta – relazione Theta):** indica che il tempo di esecuzione di un algoritmo è sia **O** che **Ω**. Quindi, il tempo di esecuzione sarà pari a **Θ(N)** se tale algoritmo è sia **O(N)** che **Ω(N)**.

fonte:[qui](https://italiancoders.it/complessita-computazionale-parte-1/)

****

## La memoria

L'occupazione della memeoria è un problema che bisogna porsi
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
L'occupazione della memeoria è un problema che bisogna porsi
L'occupazione della memoria è un problema che bisogna porsi


| stack|heap|
|------|-----|
|quante chiamate di metodo in contemporanea ho al massimo?|quanti oggetti creo?|
|quanta memoria in una singola chiamata?||

*C'è da precisare la tipologia del nostro algoritmo.*

#### Algoritmo iterativo
|stack||heap|
|------|---|-----|
|quante chiamate di metodo in contemporanea?|$1$|quanti oggetti creo?|
|quanta memoria in una singola chiamata?|costante (par. e var. locali)||

il numero di operazioni conta e c'è da chiedersi
- quante iterazioni faccio
- quante operazioni per iterazione?

#### Algoritmo ricorsivo
|stack||heap|
|------|---|-----|
|quante chiamate di metodo in contemporanea?|chiamate ricorsive in contemporanea al max?|quanti oggetti creo?|
|quanta memoria in una singola chiamata?|costante (par. e var. locali)||

il numero di operazioni conta e c'è da chiedersi
- quante chiamate ricorsive faccio in tutto?
- quante operazioni per ogni singola chiamata ricorsiva?






Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
Algoritmo per l'ordinamento di un vettore.

>Dimensione del problema: numero di elementi del vettore da ordinare

Se il vettore contiene un solo elemento allora siamo nel caso terminale, il vettore è già ordinato.

Altrimenti:
1. scegliamo un elemento del vettore (per esempio il primo); sia esso X; permutiamo gli elementi del vettore in modo da portare nella parte iniziale del vettore tutti gli elementi più piccoli di X e nella parte finale del vettore tutti gli elementi più grandi di X;
2. ordiniamo la parte iniziale del vettore (che ora contiene gli elementi più piccoli di X)
3. ordiniamo la parte finale del vettore (che ora contiene gli elementi più grandi di X) Il punto 2. ed il punto 3. sono lo stesso problema dell’ordinamento, ma applicati ad un vettore più piccolo: sono risolvibili tramite una chiamata ricorsiva.

****

Per fare un esempio supponiamo di voler ordinare il vettore:

\[42,69,24,18,26,66,69,84,19,43,3,82,64,27,11,40,7,31,33,59\]

**Primo passo**
Fissiamo un elemento per esempio il primo che è **42** permutiamo gli elementi del vettore in modo da portare nella parte iniziale del vettore tutti gli elementi più piccoli di 42 e nella parte finale del vettore tutti gli elementi più grandi di 42;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fissiamo un elemento per esempio il primo che è **42** permutiamo gli elementi del vettore in modo da portare nella parte iniziale del vettore tutti gli elementi più piccoli di 42 e nella parte finale del vettore tutti gli elementi più grandi di 42;
Fissiamo un elemento, per esempio il primo che è **42** e permutiamo gli elementi del vettore in modo da portare nella parte iniziale tutti gli elementi più piccoli di 42 e nella parte finale tutti gli elementi più grandi di 42;


\[24,18,26,19,3,27,11,40,7,31,33,**42**,69,43,66,69,84,82,64,59\]

**Secondo passo ed terzo passo**
Basta ordinare separatamente i due sotto vettori formati con la stessa modalità del primo passo.

\[24,18,26,19,3,27,11,40,7,31,33\]

\[69,43,66,69,84,82,64,59\]

dato che si tratta di risolvere il problema su una scala più piccola è risolvibile con due chiamate ricorsive.

****

I passi rappresentano anche i metodi necessari alla realizzazione del'algoritmo

**Primo passo**

_Metodo partition_. Dato un vettore di cui si considera la parte che va dalla posizione _inizio_ alla posizione _fine_, fissa un elemento detto _pivot_ (perno) permuta gli elementi in modo da portare tutti gli elementi più piccoli del perno alla sua sinistra e gli elementi più grandi del perno alla sua destra. _Restituisce la posizione finale del perno_.

static int partition(int v[], int inizio, int fine){ //O(N) = O(fine-inizio+1)
int pivot = v[inizio];
do{
while(inizo < fine && v[fine] >= pivot)
fine--;

if(inizio < fine){
v[inizio] = v[fine];
while(inizio < fine && v[inizio] <= pivot)
inizio++;

if(inizio < fine)
v[fine] = v[inizio];
}
}while(inizio < fine);
v[inizio] = pivot;
return inizio;
}
Comment on lines +40 to +57
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static int partition(int v[], int inizio, int fine){ //O(N) = O(fine-inizio+1)
int pivot = v[inizio];
do{
while(inizo < fine && v[fine] >= pivot)
fine--;
if(inizio < fine){
v[inizio] = v[fine];
while(inizio < fine && v[inizio] <= pivot)
inizio++;
if(inizio < fine)
v[fine] = v[inizio];
}
}while(inizio < fine);
v[inizio] = pivot;
return inizio;
}
```java
static int partition(int v[], int inizio, int fine){ //O(N) = O(fine-inizio+1)
int pivot = v[inizio];
do{
while(inizo < fine && v[fine] >= pivot)
fine--;
if(inizio < fine){
v[inizio] = v[fine];
while(inizio < fine && v[inizio] <= pivot)
inizio++;
if(inizio < fine)
v[fine] = v[inizio];
}
}while(inizio < fine);
v[inizio] = pivot;
return inizio;
}


**Passo due e tre**

L'algoritmo di ordinamento è dunque:

private static void quicks(int v[], int inf, int sup){
if(inf < sup){
int mid = partition(v, inf, sup); //O(sup-inf)
quicks(v,inf,mid-1);
quicks(v,mid+1,sup);
}
}

public void quicks(){ quicks (v, 0, v.length-1); }
Comment on lines +63 to +71
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private static void quicks(int v[], int inf, int sup){
if(inf < sup){
int mid = partition(v, inf, sup); //O(sup-inf)
quicks(v,inf,mid-1);
quicks(v,mid+1,sup);
}
}
public void quicks(){ quicks (v, 0, v.length-1); }
```java
private static void quicks(int v[], int inf, int sup){
if(inf < sup){
int mid = partition(v, inf, sup); //O(sup-inf)
quicks(v,inf,mid-1);
quicks(v,mid+1,sup);
}
}
public void quicks(){
quicks (v, 0, v.length-1);
}


costo in spazio è determinato dalle chiamate ricorsive attive contemporaneamente e dalla memoria occupata per ogni chiamata.

il costo in tempo è determinato da quante chiamate ricorsive faccio in tutto e da quante operazioni per chiamata.

## Complessità
Per valutare la complessità di quicksort considereremo il numero di confronti effettuati.

>All'interno della procedura partition ogni elemento viene confrontato con l'elemento $X$ che fa da perno: vengono quindi effettuati _fine-inizio+1_ confronti.

Per quanto riguarda il numero di chiamate ricorsive vediamo che il caso migliore è quello in cui ad ogni passo l'insieme viene diviso in due sottoinsiemi di dimensioni uguali.

>In questo caso sono sufficienti $log_2 (N)$ livelli di ricorsione.
![[Pasted image 20220622095234.png]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Questa immagine non è stata caricata.
Se esporti il tutto in PDF dovremmo riuscire a prenderla da li penso.

>la complessità risulta dunque di ordine $O(Nlog_2(N))$

Il caso più sfavorevole è quando $X$ è sempre l'elemento più grande o quello più piccolo dell'insieme: in questo caso l'insieme viene diviso in un insieme di un elemento ed in un insieme di _n-m_ elementi.

>In questo caso saranno necessari N livelli di ricorsione.
>![[Pasted image 20220622095348.png]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stesso discorso per questa immagine

>la complessità è di ordine $O(N^2)$
>Perché $N+(N-1)+(N-2)+… +3+2+1= (N+1)\cdot N/2$

Se scegliamo come pivot il primo elemento della parte del vettore da ordinare, il caso peggiore risulta essere quando l'insieme è già ordinato, non importa se in senso crescente o decrescente.

È possibile dimostrare che nel caso medio la complessità è di ordine $O(Nlog (N))$ con coefficiente minore di 2.
Quicksort risulta dunque mediamente meno complesso dell’algoritmo di ordinamento di scambio.

Per quanto riguarda la complessità spaziale:

| |caso migliore|caso peggiore|caso medio|
|---|-----|------|---|
|costo spaziale|$O(log(N))$|$O(N)$|$O(log(N))$|
|costo temporale|$O(Nlog_2(N))$|$O(N^2)$|$O(Nlog_2(N))$|

si dimostra che si tratta si un problema è un $\Omega (Nlog(N))$
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cosa volevi dire ?


>Per evitare di trovarsi nel caso peggiore si sceglie la posizione del pivot casualmente ad ogni passo. Riducendo in modo drastico la possibilità del caso peggiore.

****

## Implementazione non ricorsiva
Definiamo una struttura a pila in cui immagazzinare le parti del vettore ancora da ordinare: in questo modo simuliamo il meccanismo di attivazione e de attivazione degli ambienti effettuato automaticamente dalla ricorsione:

public class Elemento{
int inizio;
int fine;
Elemento next;

public Elemento(int inizio, int fine, Elemento next){
this.inizio = inizio;
this.fine = fine;
this.next = next;
}
}
Comment on lines +116 to +126
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public class Elemento{
int inizio;
int fine;
Elemento next;
public Elemento(int inizio, int fine, Elemento next){
this.inizio = inizio;
this.fine = fine;
this.next = next;
}
}
```java
public class Elemento{
int inizio;
int fine;
Elemento next;
public Elemento(int inizio, int fine, Elemento next){
this.inizio = inizio;
this.fine = fine;
this.next = next;
}
}


La pila è una struttura dati gestita con politica [[LIFO]] (Last In First Out):
l’elemento estratto è l’ultimo che è stato inserito.
La proprietà lunghezzamassima misura il massimo numero di elementi che la pila ha contenuto durante l’elaborazione.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
La proprietà lunghezzamassima misura il massimo numero di elementi che la pila ha contenuto durante l’elaborazione.
La proprietà `lunghezzamassima`` misura il massimo numero di elementi che la pila ha contenuto durante l’elaborazione.


public class Pila{
private Elemento testa = null;
private int lunghezza = 0;
private in lunghezzaMax = 0;

public void inserisci(int inizio, int fine){
testa = new Elemento(inizo, fine, testa);
lunghezza++;
if(lunghezzaMax < lunghezza)
lunghezzaMax = lunghezza;
}
public Elemento estrai (){
if (testa == null)
return null;
else {
Elemento e = testa;
testa = testa.next;
lunghezza --;
return e;
}
}
public int getLunghezzaMax(){ return lunghezzaMax;}
public int getLunghezza(){ return lunghezza;}
}
Comment on lines +132 to +155
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public class Pila{
private Elemento testa = null;
private int lunghezza = 0;
private in lunghezzaMax = 0;
public void inserisci(int inizio, int fine){
testa = new Elemento(inizo, fine, testa);
lunghezza++;
if(lunghezzaMax < lunghezza)
lunghezzaMax = lunghezza;
}
public Elemento estrai (){
if (testa == null)
return null;
else {
Elemento e = testa;
testa = testa.next;
lunghezza --;
return e;
}
}
public int getLunghezzaMax(){ return lunghezzaMax;}
public int getLunghezza(){ return lunghezza;}
}
```java
public class Pila{
private Elemento testa = null;
private int lunghezza = 0;
private in lunghezzaMax = 0;
public void inserisci(int inizio, int fine){
testa = new Elemento(inizio, fine, testa);
lunghezza++;
if(lunghezzaMax < lunghezza)
lunghezzaMax = lunghezza;
}
public Elemento estrai (){
if (testa == null)
return null;
else {
Elemento e = testa;
testa = testa.next;
lunghezza --;
return e;
}
}
public int getLunghezzaMax(){ return lunghezzaMax;}
public int getLunghezza(){ return lunghezza;}
}


Il metodo partition è esattamente lo stesso visto prima. L’implementazione non ricorsiva di quicksort diventa:
1) inserisco nella pila l’intervallo \[0, lunghezza vettore-1\]
2) while (l’elemento e che estraggo dalla pila non è nullo)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2) while (l’elemento e che estraggo dalla pila non è nullo)
2) while (l’elemento `e` che estraggo dalla pila non è nullo)

{ eseguo la partition sull’intervallo rappresentato da e inserisco nella pila i 2 sottointervalli prodotti dalla partition (per ottimizzare la dimensione della pila inseriamo per ultimo l’intervallo più piccolo, così che sia elaborato per primo) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{ eseguo la partition sull’intervallo rappresentato da e inserisco nella pila i 2 sottointervalli prodotti dalla partition (per ottimizzare la dimensione della pila inseriamo per ultimo l’intervallo più piccolo, così che sia elaborato per primo) }
{ eseguo la partition sull’intervallo rappresentato da `e`; inserisco nella pila i 2 sottointervalli prodotti dalla partition (per ottimizzare la dimensione della pila inseriamo per ultimo l’intervallo più piccolo, così che sia elaborato per primo) }



private static void quicksortNR(int v[]){
int inizio, fine, mid;
Pila p= new Pila();
Elemento e;
p.inserisci(0, v.length-1);

while ((e= p.estrai()) != null ){
inizio = e.inizio;
fine = e.fine;
mid = partition(v, inizio, fine);
if ((mid-1 -inizio ) < (fine - (mid+1))){
if (mid+1 < fine ) p.inserisci(mid+1, fine);
if (inizio < mid-1) p.inserisci(inizio, mid-1);
}
else{
if (inizio < mid-1) p.inserisci(inizio, mid-1);
if (mid+1 < fine ) p.inserisci(mid+1, fine);
}
}

System.out.println("lunghezza massima pila: "+ p.getLunghezzaMassima());
}
Comment on lines +163 to +184
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private static void quicksortNR(int v[]){
int inizio, fine, mid;
Pila p= new Pila();
Elemento e;
p.inserisci(0, v.length-1);
while ((e= p.estrai()) != null ){
inizio = e.inizio;
fine = e.fine;
mid = partition(v, inizio, fine);
if ((mid-1 -inizio ) < (fine - (mid+1))){
if (mid+1 < fine ) p.inserisci(mid+1, fine);
if (inizio < mid-1) p.inserisci(inizio, mid-1);
}
else{
if (inizio < mid-1) p.inserisci(inizio, mid-1);
if (mid+1 < fine ) p.inserisci(mid+1, fine);
}
}
System.out.println("lunghezza massima pila: "+ p.getLunghezzaMassima());
}
```java
private static void quicksortNR(int v[]){
int inizio, fine, mid;
Pila p= new Pila();
Elemento e;
p.inserisci(0, v.length-1);
while ((e= p.estrai()) != null ){
inizio = e.inizio;
fine = e.fine;
mid = partition(v, inizio, fine);
if ((mid-1 -inizio ) < (fine - (mid+1))){
if (mid+1 < fine ) p.inserisci(mid+1, fine);
if (inizio < mid-1) p.inserisci(inizio, mid-1);
}
else{
if (inizio < mid-1) p.inserisci(inizio, mid-1);
if (mid+1 < fine ) p.inserisci(mid+1, fine);
}
}
System.out.println("lunghezza massima pila: "+ p.getLunghezzaMassima());
}


L'algoritmo Quicksort è un esempio particolare di un modo generale di impostare un algoritmo, detto _divide et impera_.
Esso consiste nel dividere i dati, risolvere ricorsivamente il problema sui sottinsiemi ed ottenere la soluzione globale come combinazione delle soluzioni parziali.
Tale tecnica può portare vantaggi in termini di complessità, purché la dimensioni dei sottoinsiemi dei dati non siano troppo differenti fra loro.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Tale tecnica può portare vantaggi in termini di complessità, purché la dimensioni dei sottoinsiemi dei dati non siano troppo differenti fra loro.
Tale tecnica può portare vantaggi in termini di complessità, purché le dimensioni dei sottoinsiemi dei dati non siano troppo differenti fra loro.

Per esempio Quicksort presenta una complessità di $O(Nlog_2 N)$ quando ogni volta l'insieme da ordinare viene diviso in due parti uguali, mentre presenta una complessità di $O(N^2)$ quando ogni volta l'insieme viene diviso in una parte formata da un solo elemento ed in una parte formata dagli altri elementi.
Loading