Structures linéaires : nouveau chapitre avec listes chaînées + déplacement Pile_File
@@ -5,7 +5,8 @@
|
|||||||
| 2 - b | Diviser pour régner : tri fusion, dichotomie récursive | Exercices diviser pour régner |
|
| 2 - b | Diviser pour régner : tri fusion, dichotomie récursive | Exercices diviser pour régner |
|
||||||
| 3 - a | POO : classes, attributs, méthodes, encapsulation | TP Pokémon |
|
| 3 - a | POO : classes, attributs, méthodes, encapsulation | TP Pokémon |
|
||||||
| 3 - b | Paradigmes : fonctionnel, impératif, orienté objet | TP SpotifyWrapped |
|
| 3 - b | Paradigmes : fonctionnel, impératif, orienté objet | TP SpotifyWrapped |
|
||||||
| 4 | Structures linéaires : Pile, File — implémentation et usages | TP Pile, TP File, TP Navigateur |
|
| 4 - a | Structures linéaires : Listes chaînées — maillon, insertion, suppression, récursivité | TP Playlist |
|
||||||
|
| 4 - b | Structures linéaires : Pile, File — implémentation et usages | TP Pile, TP File, TP Navigateur |
|
||||||
| 5 - a | Bases de données : modèle relationnel, conception, clés | TP StreamFlix |
|
| 5 - a | Bases de données : modèle relationnel, conception, clés | TP StreamFlix |
|
||||||
| 5 - b | SQL : requêtes, jointures, agrégation | TP Streaming Musical |
|
| 5 - b | SQL : requêtes, jointures, agrégation | TP Streaming Musical |
|
||||||
| 6 | Arbres : arbres binaires, ABR, parcours, applications | TP Livre Dont Vous Êtes le Héros, TP Recommandation |
|
| 6 | Arbres : arbres binaires, ABR, parcours, applications | TP Livre Dont Vous Êtes le Héros, TP Recommandation |
|
||||||
|
|||||||
101
Structures_lineaires/Listes_chainees/EXERCICES.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# Exercices — Listes chaînées
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercice 1 : Comprendre les maillons
|
||||||
|
|
||||||
|
On dispose du code suivant :
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Maillon:
|
||||||
|
def __init__(self, valeur, suivant=None):
|
||||||
|
self.valeur = valeur
|
||||||
|
self.suivant = suivant
|
||||||
|
|
||||||
|
m3 = Maillon(30)
|
||||||
|
m2 = Maillon(20, m3)
|
||||||
|
m1 = Maillon(10, m2)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Représenter schématiquement la liste chaînée obtenue (avec les flèches).
|
||||||
|
2. Quelle est la valeur de `m1.suivant.valeur` ?
|
||||||
|
3. Quelle est la valeur de `m1.suivant.suivant.valeur` ?
|
||||||
|
4. Que vaut `m3.suivant` ?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercice 2 : Parcourir une liste
|
||||||
|
|
||||||
|
On dispose d'une liste chaînée `l` dont la tête pointe vers `10 → 20 → 30 → 40 → None`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def afficher(liste):
|
||||||
|
courant = liste.tete
|
||||||
|
while courant is not None:
|
||||||
|
print(courant.valeur)
|
||||||
|
courant = courant.suivant
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Dérouler manuellement l'exécution de `afficher(l)` : quelle est la valeur de `courant` à chaque tour de boucle ?
|
||||||
|
2. Combien de fois la boucle s'exécute-t-elle ?
|
||||||
|
3. Modifier la fonction pour qu'elle affiche les valeurs séparées par ` → ` sur une seule ligne (comme dans le cours).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercice 3 : Opérations de base
|
||||||
|
|
||||||
|
Implémenter les méthodes suivantes dans la classe `ListeChainee` :
|
||||||
|
|
||||||
|
1. `inserer_en_queue(self, valeur)` → ajoute un maillon à la fin de la liste.
|
||||||
|
*Indication : parcourir jusqu'au dernier maillon, puis modifier son `.suivant`.*
|
||||||
|
|
||||||
|
2. `supprimer_valeur(self, valeur)` → supprime le premier maillon contenant `valeur`.
|
||||||
|
*Cas particuliers : valeur en tête, valeur absente.*
|
||||||
|
|
||||||
|
3. `nieme(self, n)` → renvoie la valeur du n-ième maillon (indice 0 = tête).
|
||||||
|
*Lever une `IndexError` si n est hors bornes.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercice 4 : Complexité
|
||||||
|
|
||||||
|
Pour une liste chaînée de longueur n, indiquer la complexité (O(1) ou O(n)) des opérations suivantes et justifier :
|
||||||
|
|
||||||
|
| Opération | Complexité | Justification |
|
||||||
|
|-----------|------------|---------------|
|
||||||
|
| Insérer en tête | | |
|
||||||
|
| Insérer en queue | | |
|
||||||
|
| Supprimer en tête | | |
|
||||||
|
| Accéder au n-ième élément | | |
|
||||||
|
| Rechercher une valeur | | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercice 5 : Version récursive
|
||||||
|
|
||||||
|
1. Écrire la fonction récursive `longueur_rec(maillon)` qui renvoie le nombre de maillons à partir de `maillon`.
|
||||||
|
|
||||||
|
2. Écrire la fonction récursive `rechercher_rec(maillon, valeur)` qui renvoie `True` si `valeur` est présente, `False` sinon.
|
||||||
|
|
||||||
|
3. Écrire la fonction récursive `renverser(maillon)` qui renvoie une nouvelle liste chaînée dont les éléments sont dans l'ordre inverse.
|
||||||
|
*Exemple : `10 → 20 → 30 → None` devient `30 → 20 → 10 → None`.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercice 6 : Implémenter une Pile avec une liste chaînée
|
||||||
|
|
||||||
|
En utilisant `Maillon`, implémenter la classe `Pile` avec les méthodes :
|
||||||
|
- `empiler(valeur)` → ajoute au sommet
|
||||||
|
- `depiler()` → retire et renvoie le sommet
|
||||||
|
- `sommet()` → consulte le sommet sans le retirer
|
||||||
|
- `est_vide()` → renvoie `True` si la pile est vide
|
||||||
|
|
||||||
|
Tester avec : empiler 1, 2, 3, puis dépiler jusqu'à vide.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Auteur : Florian Mathieu
|
||||||
|
|
||||||
|
Licence CC BY NC
|
||||||
|
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||||
172
Structures_lineaires/Listes_chainees/README.md
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
# Listes chaînées
|
||||||
|
|
||||||
|
> Un tableau Python (`list`) permet d'accéder à n'importe quel élément en O(1) grâce aux indices — mais insérer ou supprimer un élément au milieu déplace tous ceux qui suivent. La liste chaînée adopte une autre approche : chaque élément connaît son successeur, et seuls les liens changent lors d'une modification.
|
||||||
|
|
||||||
|
## 1. Limite des tableaux pour certains usages
|
||||||
|
|
||||||
|
```python
|
||||||
|
t = [1, 2, 3, 4, 5]
|
||||||
|
t.insert(2, 99) # insère 99 à l'indice 2
|
||||||
|
# → [1, 2, 99, 3, 4, 5]
|
||||||
|
# Python a dû décaler 3, 4, 5 vers la droite : O(n)
|
||||||
|
```
|
||||||
|
|
||||||
|
Pour un tableau de 10 millions d'éléments, une insertion au début déplace 10 millions de valeurs. La liste chaînée résout ce problème : insérer en tête est toujours O(1).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Le maillon
|
||||||
|
|
||||||
|
L'unité de base d'une liste chaînée est un **maillon** (ou cellule, ou nœud). Il contient :
|
||||||
|
- une **valeur** (la donnée stockée)
|
||||||
|
- un **pointeur** vers le maillon suivant (ou `None` si c'est le dernier)
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Maillon:
|
||||||
|
def __init__(self, valeur, suivant=None):
|
||||||
|
self.valeur = valeur
|
||||||
|
self.suivant = suivant
|
||||||
|
```
|
||||||
|
|
||||||
|
On peut enchaîner des maillons manuellement :
|
||||||
|
|
||||||
|
```python
|
||||||
|
m3 = Maillon(30)
|
||||||
|
m2 = Maillon(20, m3)
|
||||||
|
m1 = Maillon(10, m2)
|
||||||
|
# m1 → m2 → m3 → None
|
||||||
|
# 10 → 20 → 30 → None
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. La classe ListeChainee
|
||||||
|
|
||||||
|
On encapsule la liste dans une classe qui mémorise uniquement la **tête** (premier maillon) :
|
||||||
|
|
||||||
|
```python
|
||||||
|
class ListeChainee:
|
||||||
|
def __init__(self):
|
||||||
|
self.tete = None # liste vide
|
||||||
|
|
||||||
|
def est_vide(self):
|
||||||
|
return self.tete is None
|
||||||
|
```
|
||||||
|
|
||||||
|
### Insérer en tête
|
||||||
|
|
||||||
|
```python
|
||||||
|
def inserer_en_tete(self, valeur):
|
||||||
|
nouveau = Maillon(valeur, self.tete)
|
||||||
|
self.tete = nouveau
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Avant : tete → [20] → [30] → None
|
||||||
|
Après : tete → [10] → [20] → [30] → None
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supprimer en tête
|
||||||
|
|
||||||
|
```python
|
||||||
|
def supprimer_en_tete(self):
|
||||||
|
if self.est_vide():
|
||||||
|
raise IndexError("Liste vide")
|
||||||
|
valeur = self.tete.valeur
|
||||||
|
self.tete = self.tete.suivant
|
||||||
|
return valeur
|
||||||
|
```
|
||||||
|
|
||||||
|
### Afficher la liste
|
||||||
|
|
||||||
|
```python
|
||||||
|
def afficher(self):
|
||||||
|
courant = self.tete
|
||||||
|
elements = []
|
||||||
|
while courant is not None:
|
||||||
|
elements.append(str(courant.valeur))
|
||||||
|
courant = courant.suivant
|
||||||
|
print(" → ".join(elements) + " → None")
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
l = ListeChainee()
|
||||||
|
l.inserer_en_tete(30)
|
||||||
|
l.inserer_en_tete(20)
|
||||||
|
l.inserer_en_tete(10)
|
||||||
|
l.afficher()
|
||||||
|
# 10 → 20 → 30 → None
|
||||||
|
```
|
||||||
|
|
||||||
|
### Longueur
|
||||||
|
|
||||||
|
```python
|
||||||
|
def longueur(self):
|
||||||
|
courant = self.tete
|
||||||
|
n = 0
|
||||||
|
while courant is not None:
|
||||||
|
n += 1
|
||||||
|
courant = courant.suivant
|
||||||
|
return n
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rechercher
|
||||||
|
|
||||||
|
```python
|
||||||
|
def rechercher(self, valeur):
|
||||||
|
courant = self.tete
|
||||||
|
while courant is not None:
|
||||||
|
if courant.valeur == valeur:
|
||||||
|
return True
|
||||||
|
courant = courant.suivant
|
||||||
|
return False
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Structure récursive
|
||||||
|
|
||||||
|
Une liste chaînée est naturellement **récursive** :
|
||||||
|
- soit elle est **vide**
|
||||||
|
- soit elle est un **maillon** (tête) suivi d'une **liste chaînée** (queue)
|
||||||
|
|
||||||
|
On peut écrire la longueur de manière récursive :
|
||||||
|
|
||||||
|
```python
|
||||||
|
def longueur_rec(maillon):
|
||||||
|
if maillon is None:
|
||||||
|
return 0
|
||||||
|
return 1 + longueur_rec(maillon.suivant)
|
||||||
|
```
|
||||||
|
|
||||||
|
Cette vision récursive ("tête + queue") est la même qu'on retrouve dans les arbres (chapitre Arbres).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Liste chaînée vs tableau Python
|
||||||
|
|
||||||
|
| | Tableau Python (`list`) | Liste chaînée |
|
||||||
|
|---|---|---|
|
||||||
|
| Accès par indice | O(1) | O(n) |
|
||||||
|
| Insertion en tête | O(n) | O(1) |
|
||||||
|
| Suppression en tête | O(n) | O(1) |
|
||||||
|
| Mémoire | Contiguë | Dispersée (maillons) |
|
||||||
|
| Usage naturel | Accès aléatoire | Insertion/suppression fréquentes |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Lien avec Pile et File
|
||||||
|
|
||||||
|
Une **pile** (LIFO) s'implémente naturellement avec une liste chaînée : `inserer_en_tete` = empiler, `supprimer_en_tete` = dépiler.
|
||||||
|
|
||||||
|
Une **file** (FIFO) s'implémente avec deux pointeurs : tête pour supprimer, queue pour insérer.
|
||||||
|
|
||||||
|
C'est précisément ce que vous allez implémenter dans le chapitre suivant.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Auteur : Florian Mathieu
|
||||||
|
|
||||||
|
Licence CC BY NC
|
||||||
|
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||||
139
Structures_lineaires/Listes_chainees/TP_Playlist.md
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# TP — Playlist musicale
|
||||||
|
|
||||||
|
> Implémenter une playlist sous forme de liste chaînée : ajouter des titres, en retirer, naviguer d'un morceau à l'autre — et comprendre pourquoi cette structure est naturellement adaptée à ce type d'usage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexte
|
||||||
|
|
||||||
|
Un lecteur de musique gère une **playlist** : une séquence de titres qu'on peut modifier en cours de route (ajouter un titre, supprimer un titre, passer au suivant). Un tableau Python serait peu adapté à ces insertions et suppressions fréquentes — la liste chaînée l'est beaucoup mieux.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 1 : La structure de base
|
||||||
|
|
||||||
|
### Étape 1 — Le maillon
|
||||||
|
|
||||||
|
Implémenter la classe `Titre` qui représente un maillon de la playlist :
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Titre:
|
||||||
|
def __init__(self, nom, artiste, suivant=None):
|
||||||
|
self.nom = nom
|
||||||
|
self.artiste = artiste
|
||||||
|
self.suivant = suivant
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.nom} — {self.artiste}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 2 — La playlist
|
||||||
|
|
||||||
|
Implémenter la classe `Playlist` :
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Playlist:
|
||||||
|
def __init__(self, nom):
|
||||||
|
self.nom = nom
|
||||||
|
self.tete = None
|
||||||
|
self.courant = None # titre en cours de lecture
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 2 : Gestion de la playlist
|
||||||
|
|
||||||
|
### Question 1
|
||||||
|
|
||||||
|
Implémenter `ajouter_en_tete(self, nom, artiste)` → ajoute un titre au début de la playlist.
|
||||||
|
|
||||||
|
### Question 2
|
||||||
|
|
||||||
|
Implémenter `ajouter_en_queue(self, nom, artiste)` → ajoute un titre à la fin.
|
||||||
|
|
||||||
|
*Quelle méthode est en O(1) ? Laquelle est en O(n) ? Pourquoi ?*
|
||||||
|
|
||||||
|
### Question 3
|
||||||
|
|
||||||
|
Implémenter `supprimer(self, nom)` → supprime le premier titre dont le nom correspond.
|
||||||
|
Gérer le cas où le titre est en tête, en milieu, ou absent.
|
||||||
|
|
||||||
|
### Question 4
|
||||||
|
|
||||||
|
Implémenter `afficher(self)` → affiche tous les titres de la playlist dans l'ordre, numérotés.
|
||||||
|
|
||||||
|
```
|
||||||
|
Playlist : "Ma playlist"
|
||||||
|
1. Bohemian Rhapsody — Queen
|
||||||
|
2. Blinding Lights — The Weeknd
|
||||||
|
3. Starboy — The Weeknd
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 3 : Lecture
|
||||||
|
|
||||||
|
### Question 5
|
||||||
|
|
||||||
|
Implémenter `lecture_suivante(self)` → passe au titre suivant dans la playlist.
|
||||||
|
- Si `courant` est `None`, commencer par la tête.
|
||||||
|
- Si `courant` est le dernier titre, retourner au début (liste circulaire).
|
||||||
|
|
||||||
|
### Question 6
|
||||||
|
|
||||||
|
Implémenter `lire(self)` → affiche le titre en cours de lecture.
|
||||||
|
|
||||||
|
```
|
||||||
|
♪ En cours : Bohemian Rhapsody — Queen
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 4 : Fonctionnalités avancées
|
||||||
|
|
||||||
|
### Question 7
|
||||||
|
|
||||||
|
Implémenter `longueur(self)` → renvoie le nombre de titres.
|
||||||
|
|
||||||
|
### Question 8
|
||||||
|
|
||||||
|
Implémenter `rechercher(self, artiste)` → renvoie la liste de tous les titres d'un artiste donné.
|
||||||
|
|
||||||
|
### Question 9 — Défi
|
||||||
|
|
||||||
|
Implémenter `melanger(self)` → réorganise les titres dans un ordre aléatoire.
|
||||||
|
|
||||||
|
*Indication : convertir la liste chaînée en tableau Python, mélanger avec `random.shuffle`, reconstruire la liste chaînée.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partie 5 : Test complet
|
||||||
|
|
||||||
|
```python
|
||||||
|
p = Playlist("Ma playlist")
|
||||||
|
p.ajouter_en_queue("Bohemian Rhapsody", "Queen")
|
||||||
|
p.ajouter_en_queue("Blinding Lights", "The Weeknd")
|
||||||
|
p.ajouter_en_queue("Starboy", "The Weeknd")
|
||||||
|
p.ajouter_en_tete("Hotel California", "Eagles")
|
||||||
|
|
||||||
|
p.afficher()
|
||||||
|
print(f"Longueur : {p.longueur()}")
|
||||||
|
|
||||||
|
p.lecture_suivante()
|
||||||
|
p.lire()
|
||||||
|
p.lecture_suivante()
|
||||||
|
p.lire()
|
||||||
|
|
||||||
|
p.supprimer("Starboy")
|
||||||
|
p.afficher()
|
||||||
|
|
||||||
|
print(p.rechercher("The Weeknd"))
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Auteur : Florian Mathieu
|
||||||
|
|
||||||
|
Licence CC BY NC
|
||||||
|
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 240 KiB |
|
Before Width: | Height: | Size: 212 KiB After Width: | Height: | Size: 212 KiB |
30
Structures_lineaires/README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Structures de données linéaires
|
||||||
|
|
||||||
|
> Un tableau Python permet d'accéder instantanément à n'importe quel élément par son indice. Mais certains problèmes demandent des structures plus souples : ajouter ou supprimer des éléments sans déplacer tout le reste, ou imposer un ordre d'accès strict. C'est l'objet de ce chapitre.
|
||||||
|
|
||||||
|
## Programme
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Les trois structures au programme
|
||||||
|
|
||||||
|
| Structure | Accès | Insertion | Suppression | Usage typique |
|
||||||
|
|-----------|-------|-----------|-------------|---------------|
|
||||||
|
| **Liste chaînée** | Séquentiel | En tête : O(1) | En tête : O(1) | Structure de base, implémente pile et file |
|
||||||
|
| **Pile** (stack) | Dernier entré (LIFO) | En tête : O(1) | En tête : O(1) | Appels de fonctions, annulation (Ctrl+Z) |
|
||||||
|
| **File** (queue) | Premier entré (FIFO) | En queue : O(1) | En tête : O(1) | File d'attente, BFS, impression |
|
||||||
|
|
||||||
|
## Ressources
|
||||||
|
|
||||||
|
| Fichier | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| [Listes chaînées](Listes_chainees/README.md) | La brique de base : maillon, insertion, suppression, parcours |
|
||||||
|
| [Piles et Files](Pile_File/README.md) | Deux structures aux contraintes d'accès strictes |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Auteur : Florian Mathieu
|
||||||
|
|
||||||
|
Licence CC BY NC
|
||||||
|
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a> <br />Ce cours est mis à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International</a>.
|
||||||