ajout cours algo + tris
This commit is contained in:
71
algorithmes/PARCOURS.md
Normal file
71
algorithmes/PARCOURS.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Parcours séquentiel d'un tableau
|
||||
|
||||
> Quelques exemples d'algorithmes qui nécessitent un parcours simple d'un tableau.
|
||||
>
|
||||
> On utilisera ici une seule boucle **for** : la complexité est donc **linéaire**.
|
||||
|
||||
On supposera que tous les tableaux traités ici contiennent des nombres.
|
||||
|
||||
### Exemples
|
||||
|
||||
#### Recherche d'occurence
|
||||
|
||||
Si on souhaite savoir si un élément nommé *e* en particulier se trouve dans un tableau *tab* :
|
||||
|
||||
```python
|
||||
def recherche(tab,e):
|
||||
occurrence = False
|
||||
for i in range (len(tab)):
|
||||
if tab[i] == b:
|
||||
occurrence = True
|
||||
return occurrence
|
||||
return occurrence
|
||||
```
|
||||
|
||||
***Complexité :***
|
||||
|
||||
Le programme effectue n+1 affectation :
|
||||
|
||||
- La première, avant la boucle.
|
||||
- Les n suivantes, selon la taille du tableau
|
||||
|
||||
Le coût est donc *linéaire* : proportionnel à n, il dépend donc de la taille du tableau, ***O(n)***
|
||||
|
||||
-------------
|
||||
|
||||
#### Recherche d'un extremum (maximum ou minimum)
|
||||
|
||||
Si on souhaite trouver le plus grand élément d'un tableau *tab* :
|
||||
|
||||
```python
|
||||
def recherche_max(tab):
|
||||
max = tab[0]
|
||||
for i in range (len(tab)):
|
||||
if tab[i] > max:
|
||||
max = tab[i]
|
||||
return max
|
||||
```
|
||||
|
||||
Complexité ?
|
||||
|
||||
--------
|
||||
|
||||
#### Calcul d'une moyenne
|
||||
|
||||
```python
|
||||
def moyenne(tab):
|
||||
m = 0
|
||||
for i in range(len(tab)):
|
||||
m = m + tab[i]
|
||||
moyenne = m // len (tab)
|
||||
return moyenne
|
||||
```
|
||||
|
||||
Complexité ?
|
||||
|
||||
-----------
|
||||
|
||||
#### Autres exemples simples :
|
||||
|
||||
- Vérifier si une un tableau est rangé par ordre croissant ou décroissant
|
||||
- Chercher un mot de plus de n lettres dans une liste de mots...
|
||||
49
algorithmes/PROPRIETES.md
Normal file
49
algorithmes/PROPRIETES.md
Normal file
@@ -0,0 +1,49 @@
|
||||
## Propriétés et caractéristiques d'un algorithme
|
||||
|
||||
Il est essentiel, pour un bon algorithme, de posséder certaines propriétés :
|
||||
|
||||
- La **terminaison** : Votre algo doit donner un résultat en un **nombre fini d'étapes** et donc ne surtout pas rester coincé dans une boucle.
|
||||
|
||||
- La **validation** : Votre algorithme doit amener au résultat attendu, peu importe la situation.
|
||||
|
||||
En plus de ces deux propriétés, on peut également citer ***le coût*** ou ***complexité*** :
|
||||
|
||||
- en **temps** : le nombre d'opérations nécessaires à son exécution
|
||||
- en **espace** : la quantité d'espace mémoire nécessaire à son exécution
|
||||
|
||||
Ici, nous ne nous intéresserons uniquement qu'au **coût en temps, la complexité temporelle.**
|
||||
|
||||
### Complexité d'un algorithme
|
||||
|
||||
On ne va pas vous demander de chronométrer l'exécution, mais plutôt de trouver **l'ordre de grandeur**.
|
||||
|
||||
Il s'agit de différencier les algorithmes selon un type de complexité : on va les grouper par *familles*.
|
||||
|
||||
Soit *n* la taille des données d'entrée, on notera la complexité d'un algorithme en fonction de *n* :
|
||||
$$
|
||||
O(f(n))
|
||||
$$
|
||||
|
||||
> On note O pour ***Ordre de grandeur***
|
||||
|
||||
| Complexité | Notation | Temps pour n = 10 | Temps pour n = 1000 | Temps pour n = 10<sup>6</sup> |
|
||||
| ------------- | ---------------- | ----------------- | ------------------- | ----------------------------- |
|
||||
| Constante | O(1) | 10 ns | 10 ns | 10 ns |
|
||||
| Logarithmique | O(log(n)) | 10 ns | 30 ns | 60 ns |
|
||||
| Linéaire | O(n) | 100 ns | 10 μs | 10 ms |
|
||||
| Quandratique | O(n<sup>2</sup>) | 1 μs | 10 ms | 2,8 heures |
|
||||
|
||||
|
||||
|
||||
```
|
||||
Pour comprendre la notion de complexité, utilisons l'exemple de tri de tableau : il s'agit d'un des cas les plus récurrents d'utilisation d'un algorithme. On a un tableau, contenant des élèments que l'on devra trier dans un ordre précis.
|
||||
|
||||
Si un algorithme met un temps donné pour trier un tableau de taille n, combien de temps lui faudra t-il pour trier un tableau 10 ou 100 fois plus grand ?
|
||||
```
|
||||
|
||||
- La **complexité d'un algorithme** est une mesure du temps requis par l'algorithme pour accomplir sa tâche, en fonction de la taille des données à traiter.
|
||||
- On dira d'un problème qu'il est aussi complexe que le meilleur algorithme connu pour le résoudre.
|
||||
- Si la **complexité** est **constante**, alors le temps d'execution sera sensiblement toujours le même, peu importe la taille du tableau traité.
|
||||
- Si elle est **logarithmique**, alors le temps d'execution augmente très faiblement quand le paramètre croit.
|
||||
- **Complexité** **linéaire** : le nombre d'étapes à effectuer va varier en proportion directe de la taille de l'échantillon à traiter : si l'échantillon croît par un facteur de 10000, la complexité sera accrue elle aussi par un facteur de 10000.
|
||||
|
||||
191
algorithmes/TRIS.md
Normal file
191
algorithmes/TRIS.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Algorithmes de tri
|
||||
|
||||
> En python, on dispose de plusieurs algorithmes permettant de trier des tableaux et relativement faciles à implémenter.
|
||||
|
||||
Il existe un problème récurrent en informatique : le tri de données. Comme vu précédemment, on travaille souvent sur de grands nombres de données, et il faut bien trier tout ça à un moment pour plusieurs raisons :
|
||||
|
||||
- espace
|
||||
- temps
|
||||
- argents
|
||||
- facilité d'utilisation
|
||||
|
||||
En python, deux méthodes permettent de trier les tableaux simplement par ordre croissant :
|
||||
|
||||
- sort()
|
||||
|
||||
```python
|
||||
>>> l = [3, 2, 1]
|
||||
>>> l.sort()
|
||||
>>> l
|
||||
[1, 2, 3]
|
||||
```
|
||||
|
||||
La méthode *sort* va modifier la liste elle-même (et renvoie *None* pour éviter les confusions).
|
||||
|
||||
Ne fonctionne qu'avec le type *list*.
|
||||
|
||||
- sorted ()
|
||||
|
||||
```python
|
||||
sorted([3, 2, 1])
|
||||
[1, 2, 3]
|
||||
```
|
||||
|
||||
Renvoie une nouvelle liste triée.
|
||||
|
||||
Fonctionne avec n'importe quel type *itérable*.
|
||||
|
||||
## Tri par insertion
|
||||
|
||||
### Présentation
|
||||
|
||||
Le tri par insertion est efficace dans le cas de tableaux de petite taille ou de tableaux triés en partie.
|
||||
|
||||

|
||||
|
||||
Le principe est ici de parcourir tous les éléments :
|
||||
|
||||
- Chaque élément est inséré à sa place dans les éléments déjà triés qui le précèdent
|
||||
- Il n'est pas nécessaire de faire une copie de la liste
|
||||
- Deux éléments égaux resteront toujours dans le même ordre
|
||||
- Les éléments peuvent être fournis au fur et à mesure
|
||||
|
||||
|
||||
|
||||
Supposons un tableau suivant :
|
||||
|
||||
```python
|
||||
tab = [9,8,5,4,7,6]
|
||||
```
|
||||
|
||||
```python
|
||||
procédure tri_insertion(tableau T)
|
||||
pour i de 1 à taille(T) - 1
|
||||
|
||||
# mémoriser T[i] dans x
|
||||
x ← T[i]
|
||||
|
||||
# décaler les éléments T[0]..T[i-1] qui sont plus grands que x, en partant de T[i-1]
|
||||
j ← i
|
||||
tant que j > 0 et T[j - 1] > x
|
||||
T[j] ← T[j - 1]
|
||||
j ← j - 1
|
||||
|
||||
# placer x dans le "trou" laissé par le décalage
|
||||
T[j] ← x
|
||||
```
|
||||
|
||||
|
||||
|
||||
Le tri par insertion est *naturel* dans l'esprit : on parcourt le tableau de la gauche vers la droite et pour chaque élément, on le classe dans la partie du tableau situé sur sa gauche.
|
||||
|
||||
### Preuve de correction
|
||||
|
||||
| Valeur de i | Tableau avant la boucle | Valeur de la clé | Tableau en fin de boucle |
|
||||
| ----------- | ----------------------- | ---------------- | ------------------------ |
|
||||
| 1 | [9,8,5,4,7,6] | 8 | [**8,9**,5,4,7,6] |
|
||||
| 2 | [8,9,5,4,7,6] | 5 | [**5,8,9**,4,7,6] |
|
||||
| 3 | [5,8,9,4,7,6] | 4 | [**4,5,8,9**,7,6] |
|
||||
| 4 | [4,5,8,9,7,6] | 7 | [**4,5,7,8,9**,6] |
|
||||
| 5 | [4,5,7,8,9,6] | 6 | [**4,5,6,7,8,9**] |
|
||||
|
||||
> À la fin de chaque boucle, le tableau est trié de la case n°0 à la case n°i
|
||||
|
||||
Une preuve de correction de l'algorithme est la propriété *p(i)* : "le tableau est trié jusqu'à la case n°i" : cette propriété est vraie **avant** et **après** chaque tour de boucle : c'est ce qu'on appelle ***Invariant de boucle***
|
||||
|
||||
À l'inverse, le **variant** de boucle est une expression dans la valeur varie à chaque tour de boucle et qui doit justement permettre de mettre fin à la-dite boucle : le variant d'un algorithme de tri sera alors la taile de la liste restante à trier.
|
||||
|
||||
### Complexité
|
||||
|
||||
Dans le pire des cas (éléments classés par ordre décroissant), la boucle while effectue 2n opérations : chaque tour de boucle for compte pour 2n + 3, répérées n - 1 fois. On a donc (n - 1) (2n + 3).
|
||||
|
||||
L'ordre de grandeur est donc de n<sup>2</sup> ou O(n<sup>2</sup> ) : on aura donc un coût **quadratique** dans le pire des cas.
|
||||
|
||||
Par contre si la liste est déjà triée, le coût est **linéaire**.
|
||||
|
||||
[Une excellente méthode pour comprendre](https://www.youtube.com/watch?v=ROalU379l3U)
|
||||
|
||||
-----------------
|
||||
|
||||
## Tri par selection
|
||||
|
||||
> Contrairement au tri par insertion, le tri par selection a pour avantage de déplacer moins de valeurs.
|
||||
|
||||

|
||||
|
||||
Principe:
|
||||
|
||||
- On recherche du plus petit élément et on le met à sa place (indice 0 donc)
|
||||
- Puis on recherche le deuxième plus petit et on le met à l'indice 1
|
||||
- Et on continue comme cela avec tous les éléments
|
||||
- Il n'est pas necessaire de faire une copie de la liste
|
||||
- Deux éléments égaux ne resteront pas forcément à la même place
|
||||
|
||||
Supposons le tableau suivant :
|
||||
|
||||
```python
|
||||
tab = [9,8,5,4,7,6]
|
||||
```
|
||||
|
||||
```python
|
||||
procédure tri_selection(tableau t)
|
||||
n ← longueur(t)
|
||||
pour i de 0 à n - 2
|
||||
min ← i
|
||||
pour j de i + 1 à n - 1
|
||||
si t[j] < t[min], alors min ← j
|
||||
fin pour
|
||||
si min ≠ i, alors échanger t[i] et t[min]
|
||||
fin pour
|
||||
fin procédure
|
||||
```
|
||||
|
||||
> En python, pour échanger des cases, on peut écrire :
|
||||
>
|
||||
> ```python
|
||||
> tab[i], tab[mini] = tab[mini], tab [i]
|
||||
> ```
|
||||
|
||||
|
||||
|
||||
### Preuve de correction
|
||||
|
||||
| Valeur de i | Tableau avant la boucle | Tableau après la boucle |
|
||||
| ----------- | ----------------------- | ----------------------- |
|
||||
| 0 | [9,8,5,4,7,6] | [**4**,8,5,9,7,6] |
|
||||
| 1 | [4,8,5,9,7,6] | [**4,5**,8,9,7,6] |
|
||||
| 2 | [4,5,8,9,7,6] | [**4,5,6**,9,7,8] |
|
||||
| 3 | [4,5,6,9,7,8] | [**4,5,6,7**,9,8] |
|
||||
| 4 | [4,5,6,7,9,8] | [**4,5,6,7,8,9**] |
|
||||
|
||||
Il faut montrer l'invariant : à la fin du tour i de la boucle for, les cases tab[0] à tab[i] incluses sont à leur place définitives.
|
||||
|
||||
### Complexité
|
||||
|
||||
- La première boucle for tourne pour i variant de 0 à n-2. Elle s'effectue donc n-2 fois.
|
||||
- La seconde boucle s'effectue n-1 - i fois.
|
||||
- On a donc n*n en ordre de grandeur, donc la complexité est de type O(n<sup>2</sup>) : **quadratique**
|
||||
|
||||
[Et donc la méthode pour mieux comprendre](https://www.youtube.com/watch?v=Ns4TPTC8whw)
|
||||
|
||||
-----
|
||||
|
||||
|
||||
|
||||
#### Exercices
|
||||
|
||||
- Ecrire les fonctions
|
||||
|
||||
```python
|
||||
tri_selection (tab)
|
||||
```
|
||||
|
||||
et
|
||||
|
||||
```python
|
||||
tri_insertion(tab)
|
||||
```
|
||||
|
||||
qui permettent de trier différement les tableaux donnés en entrée.
|
||||
|
||||
Expliquer pourquoi ces algorithmes sont en O(n<sup>2</sup> ) avec vos propres mots.
|
||||
BIN
algorithmes/assets/insertion.gif
Normal file
BIN
algorithmes/assets/insertion.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
BIN
algorithmes/assets/selection.gif
Normal file
BIN
algorithmes/assets/selection.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
Reference in New Issue
Block a user