Questa repository contiene esempi in Javascript dei più popolari algoritmi e strutture dati .
Ogni algortimo e struttura dati ha il suo README separato e la relative spiegazioni e i link per ulteriori approfondimenti (compresi quelli su YouTube).
*☝ Si noti che questo progetto è destinato ad essere utilizzato solo per l'apprendimento e la ricerca e non è destinato ad essere utilizzato per il commercio.*
## Strutture Dati
Una struttura dati è un particolare modo di organizzare e memorizzare i dati in un computer che permeta di accedervi e modificarli in modo efficiente. Più precisamente, una struttura dati è una raccolta di dati, le relazioni tra di essi e le funzioni o operazioni che possono essere applicate ai dati.
Un algoritmo è una specifica univoca per risolvere una classe di problemi. È
un insieme di regole che definiscono con precisione una sequenza di operazioni.
`P` - Principiante, `A` - Avanzato
### Algoritmi per Topic
* **Matematica**
*`P` [Manipolazione dei Bit](src/algorithms/math/bits) - set/get/update/clear bits, moltiplicazione/divisione per due, gestire numeri negativi etc.
*`P` [Fattoriale](src/algorithms/math/factorial)
*`P` [Numeri di Fibonacci](src/algorithms/math/fibonacci) - classico e forma chiusa
*`P` [Test di Primalità](src/algorithms/math/primality-test) (metodo del divisore)
*`P` [Algoritmo di Euclide](src/algorithms/math/euclidean-algorithm) - trova il massimo comune divisore (MCD)
*`P` [Minimo Comune Multiplo](src/algorithms/math/least-common-multiple) (MCM)
*`P` [Crivello di Eratostene](src/algorithms/math/sieve-of-eratosthenes) - trova i numeri i primi fino al limite indicato
*`P` [Potenza di due](src/algorithms/math/is-power-of-two) - controlla se il numero è una potenza di due
*`P` [Triangolo di Pascal](src/algorithms/math/pascal-triangle)
*`P` [Numeri Complessi](src/algorithms/math/complex-number) - numeri complessi e operazioni
*`P` [Radiante & Gradi](src/algorithms/math/radian) - conversione da radiante a gradi e viceversa
*`P` [Potenza di un Numero](src/algorithms/math/fast-powering)
*`A` [Partizione di un Intero](src/algorithms/math/integer-partition)
*`A` [Radice Quadrata](src/algorithms/math/square-root) - Metodo di Newton
*`A` [Algoritmo di Liu Hui π](src/algorithms/math/liu-hui) - calcolare π usando un poligono
*`A` [Trasformata Discreta di Fourier ](src/algorithms/math/fourier-transform) -decomporre una funzione di tempo (un segnale) nelle frequenze che lo compongono
* **Set**
*`P` [Prodotto Cartesiano](src/algorithms/sets/cartesian-product) - moltiplicazione multipla di set
*`P` [Fisher–Yates Shuffle](src/algorithms/sets/fisher-yates) - permutazione casuale di un sequenza finita
*`A` [Power Set](src/algorithms/sets/power-set) - tutti i sottoinsiemi di un set (soluzioni bitwise e backtracking)
*`A` [Permutazioni](src/algorithms/sets/permutations) (con e senza ripetizioni)
*`A` [Combinazioni](src/algorithms/sets/combinations) (con e senza ripetizioni)
*`P` [Attraversamento Lista Concatenata](src/algorithms/linked-list/traversal)
*`P` [Attraversamento Lista Concatenata nel senso Contrario](src/algorithms/linked-list/reverse-traversal)
* **Alberi**
*`P` [Ricerca in Profondità su Alberi](src/algorithms/tree/depth-first-search) (DFS)
*`P` [Ricerca in Ampiezza su Alberi](src/algorithms/tree/breadth-first-search) (BFS)
* **Grafi**
*`P` [Ricerca in Profondità su Grafi](src/algorithms/graph/depth-first-search) (DFS)
*`P` [Breadth-First Search su Grafi](src/algorithms/graph/breadth-first-search) (BFS)
*`P` [Algoritmo di Kruskal](src/algorithms/graph/kruskal) - ricerca dell'Albero con Minima Distanza (MST) per grafi pesati unidirezionali
*`A` [Algoritmo di Dijkstra](src/algorithms/graph/dijkstra) - ricerca dei percorsi più breve per raggiungere tutti i vertici del grafo da un singolo vertice
*`A` [Algoritmo di Bellman-Ford](src/algorithms/graph/bellman-ford) - ricerca dei percorsi più breve per raggiungere tutti i vertici del grafo da un singolo vertice
*`A` [Algoritmo di Floyd-Warshall](src/algorithms/graph/floyd-warshall) - ricerca dei percorsi più brevi tra tutte le coppie di vertici
*`A` [Rivelamento dei Cicli](src/algorithms/graph/detect-cycle) - per grafici diretti e non diretti (basate su partizioni DFS e Disjoint Set)
*`A` [Algoritmo di Prim](src/algorithms/graph/prim) - ricerca dell'Albero Ricoprente Minimo (MST) per grafi unidirezionali pesati
*`A` [Ordinamento Topologico](src/algorithms/graph/topological-sorting) - metodo DFS
*`A` [Punti di Articolazione](src/algorithms/graph/articulation-points) - Algoritmo di Tarjan (basato su DFS)
*`A` [Bridges](src/algorithms/graph/bridges) - basato su DFS
*`A` [Cammino Euleriano e Circuito Euleriano](src/algorithms/graph/eulerian-path) - Algoritmo di Fleury - Visita ogni margine esattamente una volta
*`A` [Ciclo di Hamiltonian](src/algorithms/graph/hamiltonian-cycle) - Visita ad ogni vertice solo una volta
*`A` [Componenti Fortemente Connessa](src/algorithms/graph/strongly-connected-components) - algoritmo di Kosaraju
*`A` [Problema del Commesso Viaggiatore](src/algorithms/graph/travelling-salesman) - il percorso più breve che visita ogni città e ritorna alla città iniziale
* **Crittografia**
*`P` [Hash Polinomiale](src/algorithms/cryptography/polynomial-hash) - Una funzione hash di rolling basata sul polinomio
* **Senza categoria**
*`P` [Torre di Hanoi](src/algorithms/uncategorized/hanoi-tower)
*`P` [Rotazione Matrice Quadrata](src/algorithms/uncategorized/square-matrix-rotation) - algoritmo in memoria
*`P` [Jump Game](src/algorithms/uncategorized/jump-game) - backtracking, programmazione dinamica (top-down + bottom-up) ed esempre di greeedy
*`P` [Percorsi Unici](src/algorithms/uncategorized/unique-paths) - backtracking, programmazione dinamica and l'esempio del Triangolo di Pascal
*`P` [Rain Terraces](src/algorithms/uncategorized/rain-terraces) - problema dell'acqua piovana in trappola(versione con programmazione dinamica e brute force)
*`P` [Recursive Staircase](src/algorithms/uncategorized/recursive-staircase) - contare il numero di percorsi per arrivare in vetta(4 soluzioni)
*`A` [Rompicapo delle Otto Regine](src/algorithms/uncategorized/n-queens)
*`A` [Percorso del Cavallo](src/algorithms/uncategorized/knight-tour)
### Modelli di Algoritmi
Un modello di algoritmo è un generico metodo o approcio che sta alla base della progettazione di una classe di algoritmi.
Si tratta di un'astrazione ancora più alta di un algoritmo, proprio come un algoritmo è un'astrazione di un programma del computer.
* **Brute Force** - controlla tutte le possibilità e seleziona la migliore
*`A` [Problema del commesso viaggiatore](src/algorithms/graph/travelling-salesman) - il percorso più breve che visita ogni città e ritorna alla città iniziale
*`A` [Trasformata Discreta di Fourier](src/algorithms/math/fourier-transform) - scomporre la funzione (segnale) del tempo in frequenze che la compongono
* **Greedy** - scegliere l'opzione migliore al momento d'eleborazione dell'algoritmo, senza alcuna considerazione per il futuro
* **Backtracking** - come la brute force, provate a generare tutte le soluzioni possibili, ma ogni volta che generate la prossima soluzione testate se soddisfa tutte le condizioni e solo allora continuare a generare soluzioni successive. Altrimenti, fate marcia indietro, e andate su un percorso diverso per trovare una soluzione. Normalmente si utilizza l'algoritmo DFS.
*`A` [Combinazioni di una Somma](src/algorithms/sets/combination-sum) - trovare tutte le combinazioni che compongono una somma
* **Branch & Bound** - ricordatevi che la soluzione meno costosa trovata ad ogni step durante il backtracking e
il costo di usare la soluzione meno costosa trovata fino al limite inferiore al costo minimo della soluzione al problema,
al fine di scartare soluzioni parziali con costi maggiori della soluzione meno costosa trovata .
Di solito si usa BFS trasversale in combinazione con DFS trasversale .
## Come usare questa repository
**Installare tutte le dipendenze**
```
npm install
```
**Eseguire ESLint**
Potresti usarlo per controllare la qualità del codice.
```
npm run lint
```
**Eseguire tutti i test**
```
npm test
```
**Eseguire un test tramite il nome**
```
npm test -- 'LinkedList'
```
**Playground**
Se vuoi puoi giocare le strutture dati e gli algoritmi nel file ./src/playground/playground.js` e
scrivere test nel file `./src/playground/__test__/playground.test.js`.
Poi puoi semplicemente eseguire il seguente comando per testare quello che hai scritto :
```
npm test -- 'playground'
```
## Informazioni Utili
### Bibliografia
[▶ Data Structures and Algorithms on YouTube](https://www.youtube.com/playlist?list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
### Notazione Big O
* La notazione Big O* è usata per classificare algoritmi in base al tempo di esecuzione o ai
requisiti di spazio che crescono in base alla crescita dell'input .
Nella grafico qua sotto puoi trovare gli ordini di crescita più comuni degli algoritmi usando la notazione Big O.
![Grafi Big O ](./assets/big-o-graph.png)
Riferimento: [Big O Cheat Sheet](http://bigocheatsheet.com/).
Nella tabella qua sotto ci sono riportate la lista delle notazioni Big O più usate e delle loro prestazioni comparate tra differenti grandezze d'input .
| Notazione Big O | Computazione con 10 elementi | Computazione con 100 elementi | Computazione con 1000 elementi |
| **Quick sort** | n log(n) | n log(n) | n<sup>2</sup> | log(n) | No | Quicksort viene eseguito in memoria solitamente con una pila di O(log(n)) |
| **Shell sort** | n log(n) | dipende dagli spazi vuoti nella sequenza | n (log(n))<sup>2</sup> | 1 | No | |
| **Counting sort** | n + r | n + r | n + r | n + r | Yes | r - numero più grande nell'array |
| **Radix sort** | n * k | n * k | n * k | n + k | Yes | k - lunghezza della chiave più grande |