Contenus | Capacités attendues | Commentaires |
---|---|---|
Structures de données, interface et implémentation. |
Spécifier une structure de données par son interface. Distinguer interface et implémentation. Écrire plusieurs implémentations d'une même structure de données. |
L'abstraction des structures de données est introduite après plusieurs implémentations d'une structure simple comme la file (avec un tableau ou avec deux piles). |
Listes, piles, files : structures linéaires. Dictionnaires, index et clé. |
Distinguer des structures par le jeu des méthodes qui les caractérisent. Choisir une structure de données adaptée à la situation à modéliser. Distinguer la recherche d'une valeur dans une liste et dans un dictionnaire. |
\_ |
Cette année, nous allons voir de nouvelles façons d'organiser et de traiter les données, ce que l'on appelle des structures de données. On rencontrera, notamment des structures linéaires comme la liste, la pile et la file, mais également des structures relationnelles telles que les arbres ou les graphes. Dans ce chapitre, nous allons commencer par distinguer la structure de données de son implémentation en s'appuyant sur les tableaux et dictionnaires vus en première.
list
en python)En première, nous avons déjà rencontré les tableaux(tableaux dynamiques pour être plus précis), qui sont des séquences d'éléments ordonnés auxquels on peut accéder facilement par leur index.
En python les tableaux sont implémentés par l'objet list
dont les
éléments sont séparés par une virgule et entourés de crochets.
# création
ma_liste = [1, "deux", 3.0]
# accès aux élements par index
ma_liste[1] # renvoie "deux"!
Les listes étant mutables, on peut ajouter ou supprimer des éléments après création.
# ajout avec la méthode `insert()`
ma_liste.insert(0, "zéro")
ma_liste # renvoie ['zéro', 1, 'deux', 3.0]
# suppression avec la méthode `pop()`
ma_liste.pop(2)
ma_liste # renvoie ['zéro', 1, 3.0]
# longueur avec la fonction `len()`
len(ma_liste) # renvoie 3 puisque ['zéro', 1, 3.0]
Python étant un langage à type dynamique, il peut convertir le type
d'une valeur en un autre suivant la situation. Ainsi si une liste se
retouve dans une situation ou un booléen est
attendu(if liste: ... while liste:
), il convertira:
False
True
Donc vérifier si une liste est vide peut-être simplement fait avec
bool(liste)
.
Les quatre méthodes qui ont été définies dans la classe list
en
Python: len
, pop
, insert
sont ce que l'on appelle une
implémentation de la structure de donnée tableau.
L'implémentation d'une structure de données ou d'un algorithme est une mise en œuvre pratique dans un langage de programmation.
Il existe de nombreux langages de programmation qui implémentent le type
abstrait , nous avions vu l'année
dernière
les différences d'implémentation entre les list
de Python et les
Array
de javascript.
Cependant, on retrouve des méthodes similaires qui sont ce que l'on appelle l'interface de la structure de données :
ajout(index, élément)
;suppr(index)
;est_vide()
;longueur()
.[Article Wikipedia sur les listes]{.cite-source}
L'interface d'une structure de données est la spécification des méthodes pouvant être appliquées sur cette structure de données.
L'intérêt de définir des structures de données avec une interface commune est de pouvoir écrire des algorithmes sur le papier en utilisant l'interface définie.
On utilise alors un pseudo-langage plus ou moins proche de la langue naturelle qui pourra être implémenté dans tous les langages de programmation ayant défini la structure de données.
Créer une classe Tableau
qui implémente les quatre méthodes ci-dessus
en stockant les données du tableau dans un attribut appelé data
de
type list
e.
Pour aller plus loin, faire l'exercice 2.
dict
ionnaires en Python)Un dictionnaire, est un type de données associant à un ensemble de clés, un ensemble de valeurs correspondantes.
Il s'agit de l'implémentation d'une structure de données abstraite appelée tableau associatif.
Les opérations usuellement fournies par un tableau associatif sont :
[Article Wikipedia sur le Tableau associatif]{.cite-source}
Les dictionnaires font partie de la bibliothèque standard de Python
grâce à la classe dict
vue en
première.
# création du dictionnaire
personne = {"nom": "Lagaffe", "prenom": "Gaston", "age": 27, "rigolo": True}
# accès à une valeur
personne['age'] # renvoie 27
Les dictionnaires étant mutables, on peut ajouter supprimer ou modifier une valeur à un dictionnaire déjà créé:
# ajout d'une clé
personne["dessinateur"] = "André Franquin"
# suppression d'une clé
del personne["rigolo"]
# modification d'une clé
personne["age"] = 28
# accès à une valeur
personne['age'] # renvoie 28
La recherche d'une valeur d'une valeur est traitée ci-après comme le propose le programme officiel.
L'article anglais de wikipédia compare diverses implémentations des tableaux associatifs.
https://en.wikipedia.org/wiki/Associative_array#Comparison
En fonction des implémentations utilisées, les opérations de recherche ou d'ajouts sont plus ou moins couteuses en temps:
Les méthodes d'itération diffèrent légèrement entre les list
es et le
dict
ionnaire en Python.
# on crée une liste vide par compréhension
paires = [2*i for i in range(10)]
print(paires) # affiche [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
def recherche_liste(liste, élément):
# itération sur les valeurs de la liste
for e in liste:
if e == élément:
return True
return False
# Appels de la fonction
recherche_liste(paires, 3) # renvoie False
recherche_liste(paires, 8) # renvoie True
On peut utiliser le mot-clé in
pour tester la présence d'une valeur
dans la liste:
>>> 8 in paires
True
>>> 7 in paires
False
Il existe trois méthodes d'itération sur les dictionnaires vues en première:
keys()
values()
items()
Pour rechercher une valeur, une itération sur les valeurs suffit.
personne = {'nom': 'Lagaffe', 'prenom': 'Gaston', 'age': 28, 'dessinateur': 'André Franquin'}
def recherche_dict(dico, valeur):
for val in dico.values():
if val == valeur:
return True
return False
recherche_dict(personne, 'André Franquin') # renvoie True
recherche_dict(personne, 'Lagafe') # renvoie False
Le mot-clé in
teste l'opérande parmi les clés et non les valeurs.
>>> 'André Franquin' in personne
False
>>> 'dessinateur' in personne
True
Nous avons déjà défini la complexité temporelle d'un algorithme qui consiste à compter le nombre d'opérations élémentaires effectuées par un algorithme pour aboutir au résultat souhaité.
Nous allons préciser ici ce que l'on entend par opération élémentaire, car parfois lorsque l'on tape une opération celle-ci n'est pas élémentaire.
Une opération est élémentaire si elle a une complexité .
list
esOpération | Exemple | Complexité |
---|---|---|
Ajout à la fin |
liste.append(e)
|
|
Insertion d'un élément |
liste.insert(i, e)
|
|
Suppression à la fin |
liste.pop()
|
|
Suppression au milieu |
liste.pop(i)
|
|
Accès à un élément |
liste\[i\]
|
|
Modification d'un élément |
liste\[i\] = e
|
|
Longueur de la liste |
len(liste)
|
|
Recherche d'un élément |
e in liste
|
[Time complexity sur le wiki Python]{.cite-source}
dict
ionnairesOpération | Exemple | Complexité |
---|---|---|
Ajout d'un élément |
dico\[clé\] = val
|
|
Modification d'un élément |
dico\[clé\] = val
|
|
Suppression d'un élément |
del dico\[clé\]
|
|
Accès à un élément |
dico\[i\]
|
|
Recherche d'une clé |
e in dico
|
|
Recherche d'un valeur |
e in dico.values()
|
Note: les complexités données sont moyennes car dans le pire des cas, toutes ses opérations sont en .
[Time complexity sur le wiki Python]{.cite-source}