Énoncé 8 : Structures de données complexes
Introduction
Durée
5 heures 20
Mots-clés
pile, liste chaînée, table de hachage, arbre binaire, arbre B
Objectif
Dans ce chapitre, vous apprendrez à :
-
manipuler les structures de données récursives que sont les listes chaînées, les arbres binaires et les arbres B ;
-
mettre en œuvre les tables de hachage ;
-
manipuler les piles.
Prérequis
Pour valider les prérequis nécessaires avant d’aborder le TP, répondez aux questions ci-après.
|
1. |
Qu’est-ce qu’une liste chaînée ? |
|
2. |
Qu’est-ce qu’une table et une fonction de hachage ? |
|
3. |
Comment est déterminée une fonction de hachage ? |
|
4. |
Qu’est-ce qu’un arbre binaire de recherche ? |
|
5. |
Qu’est-ce qu’un arbre B d’ordre n ? |
|
6. |
Qu’est-ce qu’une pile ? |
Énoncé 8.1 : La liste chaînée
Durée estimative : 50 minutes
Nous considérons une classe Donnee suivante qui permet d’associer dans un même objet, une clef de type entier et une donnée de type chaîne de caractère.
Voici la version Java de cette classe :
public class Donnee {
public int clef;
public String valeur;
public Donnee(int clef, String valeur) {
this.clef = clef;
this.valeur = valeur;
}
public String toString() {
return clef + " " + valeur;
}
}
Ainsi que la version Python équivalente :
class Donnee:
def __init__(self, clef: int, valeur: str):
self.clef: int = clef
self.valeur: str = valeur
def __str__(self) -> str:
return f"{self.clef} {self.valeur}"
Écrivez en Java/Python les classes ListeChainee et NoeudListeChainee qui gèrent l’ensemble des nœuds d’une liste chaînée. La classe ListeChainee introduit la racine de la liste ainsi que les méthodes suivantes destinées...
Énoncé 8.2 : La table de hachage
Durée estimative : 35 minutes
Écrivez en Java/Python la classe TableHachage possédant les mêmes méthodes insere, recherche et affiche que la classe ListeChainee de l’exercice précédent. La mise en œuvre de cette classe est basée sur une table de hachage de taille 10. La fonction de hachage associée est le modulo de la clef par la taille de la table, soit 10. Vous devez réaliser cette fonction en tant que méthode de la classe TableHachage.
Reprenez ensuite le programme principal de l’exercice précédent en l’adaptant pour utiliser la classe TableHachage.
Énoncé 8.3 : L’arbre binaire de recherche
Durée estimative : 75 minutes
Pour cet exercice, vous travaillez sur une nouvelle structure de données : l’arbre binaire de recherche. Vous vous basez sur la structure de classes introduite dans l’exercice 8.1.
Écrivez en Java/Python les classes ArbreBinaire et NoeudArbreBinaire, qui possèdent les mêmes méthodes insere, recherche et affiche que les classes ListeChainee et NoeudListeChainee de l’exercice 8.1.
La méthode affiche doit produire un résultat indenté pour montrer la forme de l’arbre. Par exemple, pour le dernier arbre de la figure de la page suivante, l’affichage doit être le suivant (les nœuds gauches apparaissent avant les nœuds droits) :
7 7
10 10
11 11
14 14
15 15
Reprenez ensuite le programme principal de l’exercice 8.1 en l’adaptant pour utiliser la classe ArbreBinaire.
Indice
L’insertion dans un arbre binaire se fait en recherchant la valeur de la clef de la donnée à insérer dans l’arbre binaire. Si elle n’est pas trouvée, l’algorithme consiste à ajouter un sous-nœud au dernier nœud parcouru de la recherche. Ce sous-nœud est inséré à gauche si la valeur de la clef de la donnée à insérer...
Énoncé 8.4 : L’arbre B (ou B-arbre)
Durée estimative : 100 minutes
Nous travaillons à nouveau sur une nouvelle structure de données : l’arbre B. Nous nous basons encore une fois sur la structure de classes introduite dans l’exercice 8.1. Il convient donc d’écrire en Java/Python les classes ArbreB et NoeudArbreB qui possèdent les mêmes méthodes insere, recherche et affiche que les classes ListeChainee et NoeudListeChainee de l’exercice 8.1.
Comme l’insertion dans un arbre B est un algorithme complexe, nous fournissons celui-ci ci-après. Vous trouverez d’abord la version Java, puis la version Python, et pour chaque langage, d’abord la classe ArbreB, puis la classe NoeudArbreB.
En Java, la classe ArbreB ainsi que les attributs et le constructeur de cette classe.
public class ArbreB {
NoeudArbreB racine;
int ordre;
public ArbreB(int ordre) {
this.ordre = ordre;
racine = new NoeudArbreB(ordre);
}
public void insere(int nouvelleClef, String donnee) {
Donnee nouvelleDonnee = new Donnee(nouvelleClef, donnee);
NoeudArbreB noeudDroitNouvelleDonnee = new NoeudArbreB(ordre);
nouvelleDonnee = racine.insere(nouvelleDonnee,
noeudDroitNouvelleDonnee);
if (nouvelleDonnee == null)
return;
NoeudArbreB nouvelleRacine = new NoeudArbreB(ordre);
nouvelleRacine.donnees[0] = nouvelleDonnee;
nouvelleRacine.enfants[0] = racine;
nouvelleRacine.enfants[1] = noeudDroitNouvelleDonnee;
nouvelleRacine.nbrDonnees = 1;
racine = nouvelleRacine;
}
// méthodes affiche et recherche à écrire
}
Pour la classe NoeudArbreB en Java, la méthode insere, le constructeur et les attributs sont décrits à la suite.
public class NoeudArbreB {
Donnee...Énoncé 8.5 : La Pile
Durée estimative : 25 minutes
Le but de l’exercice est d’écrire la classe Pile décrivant une pile de chaînes de caractères. La représentation interne de la pile est réalisée avec un tableau de taille fixe. Cette taille est transmise au constructeur.
Cette classe Pile introduit les méthodes empile et depile :
-
La méthode empile prend une chaîne de caractères à ajouter au sommet de la pile et renvoie un booléen. Si l’insertion est possible (tableau interne non rempli), la méthode empile renvoie le booléen vrai. Elle renvoie le booléen faux dans le cas contraire.
-
La méthode depile renvoie la chaîne de caractères située au sommet de la pile ou null (Java)/None (Python) si la pile est vide.
Écrivez en Java/Python la classe Pile ainsi que le programme principal qui empile des chaînes de caractères lues au clavier tant que l’empilement est possible.
Énoncé 8.6 : Les expressions postfixées
Durée estimative : 35 minutes
L’exercice consiste à écrire un interpréteur d’expressions postfixées dans lesquelles les opérateurs sont placés après les opérandes. Par exemple, au lieu d’écrire 2 + 3, il faut écrire 2 3 +. Au lieu de 2 + 3 * 5, il faut écrire 2 3 5 * +. Le principe est qu’un opérateur remplace les deux derniers opérandes par le résultat de l’opération. Ainsi 2 3 5 * + est transformé en 2 15 + puis 17.
Écrivez en Java/Python la classe ExpressionPostFixee qui permet de calculer des expressions postfixées. Cette classe est basée sur l’utilisation d’un objet de la classe Pile. Une pile de taille 5 permet de calculer des expressions très complexes.
La classe ExpressionPostFixee introduit quatre méthodes :
-
empileValeur (Java)/empile_valeur (Python) qui permet d’introduire un nouvel opérande (qui est empilé) de type entier ;
-
add qui dépile les deux derniers opérandes et empile le résultat de l’addition ;
-
mult qui dépile les deux derniers opérandes et empile le résultat de la multiplication ;
-
resultat qui dépile la dernière valeur empilée et la renvoie comme résultat...