Votre opinion sur le cours de ce matin : | Votre opinion sur le TD de la semaine dernière : |
Java fournit une syntaxe agréable pour parcourir les éléments de
toute classe qui implémente l'interface
Iterable
.
Ainsi, on peut écrire :
void print (Iterable<Integer> it) { for (int v : it) { System.out.println(v); } }On peut écrire une telle boucle
for
pour toute classe faisant partie des
collections
Java, telle
que LinkedList
par exemple. On peut également définir sa propre classe
Iterable
, de la manière suivante :
class C implements Iterable<Integer> { public Iterator<Integer> iterator() { return new Iterator<Integer> () { public boolean hasNext() {...} public Integer next() {...} } } }
Ici, la classe C
implémente une structure de données
dont on veut pouvoir parcourir les éléments.
Elle fournit pour cela une méthode iterator
qui renvoie une nouvelle instance de la classe
Iterator
,
qui elle-même fournit des méthodes hasNext
et next
. La méthode hasNext
renvoie true
s'il reste des éléments à parcourir,
et false
sinon.
La méthode next
renvoie le prochain élément
de l'itération; s'il n'y a plus d'élément à renvoyer,
elle lève l'exception NoSuchElementException
.
Implémenter une classe Interval
dont le constructeur
prend deux entiers beginning
et end
.
L'itérateur de la classe Interval
doit parcourir les
entiers compris entre
beginning
(inclus) et end
(exclus), dans
l'ordre croissant.
Tester votre code avec plusieurs intervalles, par exemple
[-10,10]
, [10,10]
, ou [1,0]
.
Vérifier également que l'on peut itérer plusieurs fois sur un même object
de classe Interval
.
Faites d'abord vos propres tests. Puis vérifiez à l'aide de nos tests.
Déposer le fichier Interval.java :
On suppose données deux instances
de Iterator<Integer>
, chacune énumérant une
séquence d'entiers dans l'ordre croissant.
Écrire une classe MergeIterator
qui énumère la
réunion de ces deux séquences, dans l'ordre croissant.
On pourra utiliser deux champs qui stockent
le prochain élément de chaque itérateur, s'il existe,
et null
sinon.
public class MergeIterator implements Iterator<Integer> { public MergeIterator(Iterator<Integer> it1, Iterator<Integer> it2) { ... } ... }Pour tester votre code, vous pouvez utiliser les itérateurs sur un intervalle écrits lors de la question précédente. N'oubliez pas de tester les cas où l'une des séquences est vide, les cas où l'une des séquences est plus longue que l'autre, les cas où les séquences ont des éléments communs, etc.
Faites d'abord vos propres tests. Puis vérifiez à l'aide de nos tests.
Déposer le fichier MergeIterator.java :
On considère une classe
Tree<V>
représentant des arbres binaires
dont les nœuds contiennent des valeurs de
type V
:
public class Tree<V> { V val; Tree<V> left, right; Tree<V> parent; public Tree(V val, Tree<V> left, Tree<V> right) {...} }Noter que les champs
left
et right
peuvent
contenir le pointeur null
.
Noter également que chaque nœud contient un pointeur, stocké
dans le champ parent
,
vers son père, s'il en a un.
Ce pointeur est nul si ce nœud n'a pas de père.
Votre constructeur doit faire en sorte que ce champ
soit correctement initialisé.
L'objectif est ici de faire de la classe
Tree
une classe Iterable
.
Définir un itérateur pour le parcours infixe
(in-order
en anglais) : d'abord le sous-arbre gauche, puis la racine,
enfin le sous-arbre droit.
La classe de l'itérateur maintient un champ
current
contenant le prochain nœud à visiter.
Attention: les arbres ne doivent pas être modifiés (pas même le
champ parent
).
Testez directement à l'aide de nos tests.
Déposer le fichier Tree.java :
Réaliser un autre itérateur qui parcourt les éléments de l'arbre dans l'ordre préfixe (pre-order en anglais) : la racine, le sous-arbre gauche, enfin le sous-arbre droit.
Déposer le fichier Tree.java :Une solution vous est proposée.