
Capitolo ID 1: Introduzione agli algoritmi
qualcosa che siamo chiamati a risolvere
un particolare input ad un problema
una sequenza di istruzioni che istruiscono sull'esecuzione di un determinato compito
Chi è l'esecutore dell'algoritmo:
chi esegue l'algoritmo e conosce il linguaggio con il quale è stato scritto
La seguente frase è "ambigua":
lo studio del miglior modo per esprimere un concetto
stesso risultato indipendentemente dall'esecutore
esiste una condizione da valutare e due possibili gruppi di istruzioni da eseguire
modifica il valore di una variabile
Qualunque algoritmo può essere implementato usando le sole seguenti strutture:
sequenza, ciclo e selezione
Nella tesi di Church-Turing:
tutti i linguaggi sufficientemente espressivi sono ugualmente espressivi
La sequenza delle operazioni è rappresentata da:
valuta un'espressione e poi visualizza il risultato sullo schermo
legge un input ed immagazzina tale valore in una variabile
Nella selezione, in funzione del valore della condizione, si sceglie un blocco oppure l'altro:
si modifica il valore di una variabile
While {condizione} do {corpo} end while:
Il seguente pseudocodice (a, b) < - (b,a):
indica uno scambio del valore delle variabili
Il seguente pseudocodice arr[{espr}]:
indica un valore specifico all'interno dell'array
Nella ricerca sequenziale di un elemento in un array di n elementi:
la complessità è proporzionale ad n
Nella ricerca sequenziale di un elemento in un array di n elementi:
l'ordinamento non ha un impatto sulla complessità della ricerca sequenziale
l'array deve essere ordinato
la complessità è logaritmica
Nella ricerca binaria, la procedura ricorsiva:
lavora su sottoinsiemi dell'array
Nell'analisi di un algorimo è importante considerare correttezza, completezza e:
Un algoritmo è corretto quando:
restituisce sempre una risposta corretta
Fornire la complessità dell'algoritmo corretto:
significa dare almeno un tetto alla complessità del problema risolto dall'algoritmo
Se l'algoritmo trovato non è il migliore per risolvere quel problema:
non avremo risposto alla domanda qual è la complessità del mio problema
Il dato di ingresso soddisfa una certa proprietà:
È un tipo di problema decisionale
Un problema di ottimizzazione:
cerca una soluzione a costo minimo
Stabilire se un grafo è connesso:
È un problema decisionale
Nella programmazione dinamica:
la soluzione viene costruita a partire da un insieme di sotto-problemi potenzialmente ripetuti
Prova a fare qualcosa, se non funziona disfala e prova a farne un'altra:
L'approccio bottom-up è tipico di:
La scelta migliore nell'immediata è tipica di:
È una fase del divide et impera
È tipica del divide et impera
Nella torre di Hanoi con 4 dischi il numero di mosse necessarie è:
Una delle seguenti non è una operazione elementare:
La complessità asintotica:
stima quanto aumenta il tempo di calcolo al crescere della dimensione n dell'input
La notazione Theta rappresenta:
La notazione asintotica O:
vale per ogni n maggiore o uguale ad un certo valore n con 0
Una funzione polinomiale è:
Una funzione polinomiale è:
La notazione asintotica Omega:
vale per ogni n maggiore o uguale ad un certo valore n con 0
Nel logaritmo, O(n) ed Ω(n):
Se una funzione è sia O(g(n)) che Ω(g(n):
La notazione asintotica Theta ammette che esistano 2 costanti c1 e c2:
per ogni n maggiore o uguale ad un certo valore n con 0
La notazione asintotica O:
rappresenta un limite inferiore asintotico
Il limite superiore di una espressione polinomiale è:
Il limite inferiore di una espressione polinomiale è:
Se il limite per n tendente all'infinito di f(n)/g(n) è 0:
Se il limite per n tendente all'infinito di f(n)/g(n) è infinito:
f(n) è Omega grande di g(n)
Se il limite per n tendente all'infinito di f(n)/g(n) è un numero finito:
f(n) è Theta grande di g(n)
La seguente non è una proprietà dei limiti asintotici:
La 'o' piccola implica la 'O' grande:
complessità pseudolineare
Quale tra le seguenti ha una complessità maggiore al crescere di n:
Nei diagrammi di flusso, il simbolo del rombo è usato per:
Nella selezione sono possibili:
Nell'iterazione sono possibili esclusivamente:
Nella ripetizione "mentre" è solo possibile specificare:
Nella ripetizione "per" è solo possibile specificare come "direzione":
In Flowgorithm la ripetizione è identificata da una forma:
Il seguente non è un numero sconnesso:
Un numero è definito come sconnesso se per ogni sua cifra:
la cifra adiacente a destra e a sinistra dista al massimo 1
Il seguente è un numero sconnesso:
Il seguente è un numero sconnesso:
Il seguente è un numero sconnesso:
Il seguente è un numero sconnesso:
Gli ambienti di Replit sono chiamati:
Quale dei seguenti non è un token in Pseudocode:
Quale dei seguenti non è un token in Pseudocode:
Quale dei seguenti non è un token in Pseudocode:
In Pseudocode una funzione:
deve restituire un valore
In Pseudocode le iterazioni ammesse sono:
In Pseudocode il for necessità:
In Pseudocode il while necessità:
determinato dalla somma dei tempi d'esecuzione di tutte le istanze dei dati di ingresso, con ogni addendo moltiplicato per la probabilità di occorrenza della relativa istanza dei dati di ingresso
In una sequenza di istruzioni, la complessità è:
O grande del massimo delle funzioni relative a ciascuna sequenza
Nel fattoriale non ricorsivo:
In Fibonacci non ricorsivo per n = 3:
In Fibonacci non ricorsivo per n = 2:
Nel calcolo del massimo non ricorsivo:
Nel calcolo del massimo non ricorsivo, il caso peggiore ha complessità:
Nel calcolo del massimo non ricorsivo, il caso migliore ha complessità:
Nel calcolo del massimo non ricorsivo, avere il massimo in prima posizione:
non comporta vantaggi alla complessità
Nel calcolo del massimo non ricorsivo, avere il massimo in ultima posizione:
non comporta vantaggi alla complessità
Una equazione di ricorrenza esprime il tempo di esecuzione totale di un problema di dimensione n:
in funzione del tempo di esecuzione per input più piccoli
La ricorrenza che si ottiene nel divide et impera è nella forma:
Nel divide et impera, D(n) è usato per indicare:
il tempo per dividere il problema in sotto-problemi
Nel divide et impera, C(n) è usato per indicare:
il tempo per combinare i sotto-problemi
Nel metodo di sostituzione:
ipotizziamo un limite e poi usiamo l'induzione matematica per dimostrare che la nostra ipotesi è corretta
L'ipotesi che si ottiene tramite un albero di ricorsione:
può essere usata nel metodo di sostituzione
Consideriamo T(n)=9T(n/3)+n:
Nel teorema dell'esperto si confronta f(n) con:
Nel teorema dell'esperto si hanno il seguenti numero di casi di analisi:
Le strutture nell'ambito della programmazione possono essere definite ad un livello astratto:
come insiemi di elementi dotati di opportune operazioni
contenitore statico ed omogeneo di valori, variabili o oggetti
Un array è detto statico perché:
i suoi elementi non variano di numero a tempo d'esecuzione
Un array è detto omogeneo perché:
i suoi elementi sono tutti dello stesso tipo
L'operazione di lettura o modifica del valore di un elemento di un array ha complessità asintotica:
Gli elementi di un array sono memorizzati:
In un array, il problema della visita:
significa attraversare tutti i suoi elementi esattamente una volta
non supporta nativamente gli array
Le prestazioni di un array in C++ rispetto ad una analoga Python list:
In C/C++ vi sono a disposizione del programmatore, i seguenti pools di memoria:
Tipo di memoria che persiste per l'intera esecuzione del programma ed è utilizzata tipicamente per memorizzare variabili globali:
manualmente dal programmatore
L'allocazione dello stack:
È gestita dal compilatore
Uno dei problemi dello stack è:
L'operatore & nei puntatori è usato:
per ottenere l'indirizzo di un oggetto
L'operatore * nei puntatori è usato:
per accedere all'oggetto riferito
Gli operatori new e delete in C++ sono usati per:
gestire l'allocazione dinamica e la deallocazione degli oggetti
La dichiarazione di un puntatore comporta:
allocazione di memoria per una variabile puntatore, ma non per la variabile puntata
La dichiarazione di un array comporta:
allocazione di memoria non solo per una variabile puntatore, ma anche per l'area puntata
L'algoritmo di visita di un array è:
L'algoritmo di ricerca lineare in un array è:
L'algoritmo di ricerca binaria in un array è:
applicabile solo se l'array è ordinato
Il costo di un algoritmo di ricerca binaria è:
Il costo di un algoritmo di ricerca lineare in C++ e Python è:
Il costo di un algoritmo di ricerca binaria in C++ e Python è:
Un algoritmo di ricerca binaria:
si può implementare in modalità ricorsiva ed iterativa
Gli Unit Tesrs in Python:
non impattano sulla complessità dell'algoritmo
L'ordinamento di una sequenza di informazioni consiste nel disporre:
le stesse informazioni in modo da rispettare una qualche relazione d'ordine di tipo lineare
Un algoritmo di ordinamento è stabile se:
non altera l'ordine relativo di elementi dell'array aventi la stessa chiave
Un algoritmo di ordinamento opera in place se:
la dimensione delle strutture ausiliarie di cui necessita è indipendente dal numero di elementi dell'array da ordinare
Gli algoritmi di Ordinamento Interno:
fanno uso di strutture dati allocate in memoria centrale dell'elaboratore
Gli Algoritmi Semplici di Ordinamento presentano una complessità:
È stabile ma non in place
In selection Sort la complessità nel caso migliore è:
In selection Sort la complessità ne caso medio è:
In selection Sort la complessità ne caso peggiore è:
Selection Sort è in generale:
Selection Sort è in place:
Selection Sort nel caso peggiore:
Selection Sort nel caso peggiore:
Selection Sort nel caso medio:
Selection Sort non è stabile perché:
altera gli elementi chiave
Selection Sort è in place perché:
non introduce strutture dati ausiliarie che dipendono dalla grandezza dell'array
In Insertion Sort la complessità nel caso migliore è:
In Insertion Sort la complessità nel caso medio è:
In Insertion Sort la complessità nel caso peggiore è:
Insertion Sort è in generale:
Insertion Sort è in place:
Insertion Sort nel caso peggiore:
Insertion Sort nel caso peggiore:
Insertion Sort nel caso medio:
Insertion Sort è stabile perché:
non altera gli elementi chiave
Insertion Sort è in place perché:
non introduce strutture dati ausiliarie che dipendono dalla grandezza dell'array
In Bubble Sort la complessità nel caso migliore è:
In Bubble Sort la complessità nel caso medio è:
In Bubble Sort la complessità nel caso peggiore è:
Bubble Sort è in generale:
Bubble Sort nel caso peggiore:
Bubble Sort nel caso peggiore:
Bubble Sort nel caso medio:
Bubble Sort è stabile perché:
non altera gli elementi chiave
Bubble Sort è in place perché:
non introduce strutture dati ausiliarie che dipendono dalla grandezza dell'array
In Merge Sort la complessità nel caso migliore è:
In Merge Sort la complessità nel caso medio è:
In Merge Sort la complessità nel caso peggiore è:
Merge Sort è in generale:
Merge Sort nel caso peggiore:
Merge Sort nel caso peggiore:
Merge Sort nel caso medio:
Merge Sort è stabile perché:
non altera gli elementi chiave
Merge Sort è in place perché:
introduce strutture dati ausiliarie che dipendono dalla grandezza dell'array
In Quick Sort la complessità nel caso migliore è:
In Quick Sort la complessità nel caso medio è:
In Quick Sort la complessità nel caso peggiore è:
Quick Sort è in generale:
Quick Sort nel caso peggiore:
Quick Sort nel caso peggiore:
Quick Sort nel caso medio:
Quick Sort non è stabile perché:
altera gli elementi chiave
Quick Sort è in place perché:
non introduce strutture dati ausiliarie che dipendono dalla grandezza dell'array
tutte le foglie hanno la stessa profondità e tutti i nodi interni hanno grado 2
In un albero quasi completo:
tutti i livelli, tranne al più l'ultimo, sono completi
Il grado di un albero indica:
il numero di figli di uno specifico nodo
In un albero heap, left(i) è pari a:
ogni elemento è minore o uguale al nodo padre
si può usare sia il max-heap che il min-heap
Nella prima fase dell'heap sort, l'algoritmo permuta i valori contenuti negli elementi dell'array in modo tale che:
la nuova disposizione delle chiavi costituisca uno heap
In un albero heap, right(i) è pari a:
Nell'heap sort, le operazioni parent, left e right possono essere calcolate:
mediante una sola operazione
il più piccolo elemento è nella radice
In Heap Sort la complessità nel caso migliore è:
In Heap Sort la complessità nel caso medio è:
In Heap Sort la complessità nel caso peggiore è:
Heap Sort nel caso peggiore:
Heap Sort nel caso peggiore:
Heap Sort nel caso medio:
Heap Sort non è stabile perché:
altera gli elementi chiave
Heap Sort è in place perché:
non introduce strutture dati ausiliarie che dipendono dalla grandezza dell'array
fornisce una rappresentazione organizzata e logica dei dati all'interno di un insieme
Una struttura dinamica è una struttura che è pensata:
per aggiungere o togliere elementi durante l'esecuzione di un algoritmo
Se non si possono cioè fare ipotesi sulla posizione fisica degli elementi in memoria si dice che la struttura è:
Un array è una struttura:
Le tipiche operazioni su un insieme dinamico sono:
Una struttura dati concreta:
È l'implementazione di una struttura astratta
di identificare univocamente i dati in una struttura
Nelle strutture dati dinamiche i puntatori:
In Python, tutte le variabili:
In Python, quando si assegna un valore a una variabile:
si sta creando un riferimento all'oggetto in memoria
Rispetto alla tassonomia classica, una lista risulta:
dinamica, sparsa, ordinata
Nelle liste, il puntatore:
È usato per l'implementazione
Gli elementi di una lista:
non sono necessariamente memorizzati in modo consecutivo
Una lista è un multi-insieme, cioè:
ci possono essere ripetizioni del medesimo elemento
Dati una lista e un valore, stabilire se il valore è contenuto in un elemento della lista, riportando in caso affermativo l'indirizzo di tale elemento:
È il problema della ricerca
Una lista dinamica può essere rappresentata tramite:
La ricerca di un elemento in una lista:
Malloc() in C ha come analoga in C++:
Free() in C ha come analoga in C++:
Se non si libera la memoria allocata dinamicamente:
si rischia un memory leak
fornisce una rappresentazione organizzata e logica dei dati all'interno di un insieme
Una struttura dinamica è una struttura che è pensata:
per aggiungere o togliere elementi durante l'esecuzione di un algoritmo
Se non si possono cioè fare ipotesi sulla posizione fisica degli elementi in memoria si dice che la struttura è:
Un array è una struttura:
Le tipiche operazioni su un insieme dinamico sono:
Una struttura dati concreta:
È l'implementazione di una struttura astratta
di identificare univocamente i dati in una struttura
Nelle strutture dati dinamiche i puntatori:
In Python, tutte le variabili:
In Python, quando si assegna un valore a una variabile:
si sta creando un riferimento all'oggetto in memoria
Rispetto alla tassonomia classica, una lista risulta:
dinamica, sparsa, ordinata
Nelle liste, il puntatore:
È usato per l'implementazione
Gli elementi di una lista:
non sono necessariamente memorizzati in modo consecutivo
Una lista è un multi-insieme, cioè:
ci possono essere ripetizioni del medesimo elemento
Dati una lista e un valore, stabilire se il valore è contenuto in un elemento della lista, riportando in caso affermativo l'indirizzo di tale elemento:
È il problema della ricerca
Una lista dinamica può essere rappresentata tramite:
La ricerca di un elemento in una lista:
Malloc() in C ha come analoga in C++:
Free() in C ha come analoga in C++:
Se non si libera la memoria allocata dinamicamente:
si rischia un memory leak