Amphi 4 1
Plan
• Piqûre de rappel sur les références
• Evaluation d'expressions arithmétiques
• Variables et méthodes statiques
• Vocabulaire sur les arbres
Amphi 4 2
Retour sur les références
class Code {
int numero;
Code(int n) {
numero = n;
} }
Retour sur les références (2)
static void f(int c) {
c = 4321;
}
static void g(Code c) {
c.numero = 4321;
}
Retour sur les références (3)
public static void main(String[] args) {
Code c = new Code(1234);
System.out.println(c.numero);
f(c.numero);
System.out.println(c.numero);
g(c);
System.out.println(c.numero);
}
Qu'affiche le programme ?
Amphi 4 5
Plan
• Piqûre de rappel sur les références
• Evaluation d'expressions arithmétiques
• Variables et méthodes statiques
• Vocabulaire sur les arbres
Amphi 4 6
Arbre d'une expression arithmétique
( ( a/ ( (b-c)+d ) ) *(e-a) ) *c *
* / -
+ -
c
a e a
b c
d
Amphi 4 7
Notation postfixée (polonaise)
Forme postfixée abc-d+/ea-*c*
Les opérandes sont écrits avant
l'opérateur
( ( a/ ( (b-c)+d ) ) *(e-a) ) *c *
* / -
+ -
c
a e a
b c
d
Amphi 4 8
Evaluation des expressions arithmétiques
• Beaucoup plus simple sous forme postfixée.
• Utilisation d'une pile. Une seule règle : lorsqu'un opérateur est en entrée, on dépile les opérandes et on empile le résultat.
6 3 2 - 1 + / 9 6 - *
6 3 2
6 1
6 1 1
6 2
3 9
3 9 6
3 3
9
(6/(3-2+1))*(9-6)
- + /
3
- *
Amphi 4 9
Expressions arithmétiques en Java (1)
class Terme {
boolean estNombre;
int nombre;
char operateur;
}
Amphi 4 10
Expressions arithmétiques en Java (2)
class ExpressionPostfixe {
static int calculer(int x, char a, int y) { ... }
static void evaluer(Terme x, Pile p) { ... }
static int evaluer(Terme[] u) { ... }
}
Trois méthodes principales
Expressions arithmétiques en Java (3)
static int calculer(int x, char a, int y) {
switch (a) {
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
}
return -1; // sinon }
Expressions arithmétiques en Java (4)
static void evaluer(Terme x, Pile p) throws PileException {
if (x.estNombre)
Pile.ajouter(x.nombre, p);
else {
int a = Pile.valeur(p);
Pile.supprimer(p);
int b = Pile.valeur(p);
Pile.supprimer(p);
int c = calculer(b, x.operateur, a);
Pile.ajouter(c, p);
}
} // variante dans le poly
Amphi 4 13
Expressions arithmétiques en Java (5)
static int evaluer(Terme[] u) throws PileException
{
Pile p = new Pile();
for (int i = 0; i < u.length ; ++i) evaluer(u[i], p);
return Pile.valeur(p);
} // variante dans le poly
Amphi 4 14
Evaluation d'une expression (6)
try {
int valeur = evaluer(expression);
System.out.println("La valeur est "
+ valeur);
}
catch (PileException e) {
System.out.println("Erreur dans l'évaluation");
}
Amphi 4 15
Plan
• Piqûre de rappel sur les références
• Evaluation d'expressions arithmétiques
• Variables et méthodes statiques
• Vocabulaire sur les arbres
Amphi 4 16
Variables statiques (1) Une variable déclarée static est commune à tous les objets de la classe. Pour cette raison, on parle de variable de classe.
Toute modification d'une variable statique dans un objet quelconque de la classe est visible par tous les objets de la classe.
Exemple : Math.Pi (Pi est une variable final static de la classe Math)
Variable non statique --> une instance par objet.
Amphi 4 17
Variables statiques (2)
class Paire {
static int x;
int y;
}
Amphi 4 18
Variables statiques (2)
class Test {
static void main() {
Paire s = new Paire();
System.out.println("s.x = " + s.x +
", s.y = " + s.y +
", Paire.x = " + Paire.x);
} }
>s.x = 0, s.y = 0, Paire.x = 0
Variables statiques (3)
class Test {
static void main() { Paire s = new Paire ();
Paire t = new Paire ();
t.x = 2; t.y = 3;
System.out.println("t.x = " + t.x + ", t.y = " + t.y);
System.out.println("s.x = " + s.x + ", s.y = " + s.y);
} }
>t.x = 2, t.y = 3
>s.x = 2, s.y = 0
Méthodes statiques Une méthode déclarée static peut être utilisée sans référence à un objet particulier. On parle alors de méthode de classe.
Une méthode statique n'a pas directement accès aux variables non statiques.
On peut appeler une méthode statique par NomdeClasse.nomDeMethode()
Exemple : Math.abs() (abs() est une méthode
statique de la classe Math)
Amphi 4 21
Méthodes non statiques Une méthode qui n'est pas déclarée static est toujours utilisée en référence à un objet. On parle de méthode d'objet.
On peut appeler une méthode non statique par nomObjet.nomDeMethode()
Le mot clé this désigne l'objet courant. Il n'a jamais la valeur null, et sa valeur ne peut être modifiée.
Utiliser this dans une méthode statique produit une erreur à la compilation.
Amphi 4 22
System.out.println()
• La classe System contient une variable de classe de nom out.
• L'objet System.out appelle une méthode d'objet de nom println().
Amphi 4 23
Méthodes statiques (2)
class Paire {
static int x; int y;
void affiche_x() { // méthode d'objet System.out.println("s.x = " + this.x);
}
void affiche_y() { // méthode d'objet System.out.println("s.y = " + this.y);
}
static void affiche2_x() { // de classe System.out.println("s.x = " + x);
}
static void affiche3_y(Paire s) { System.out.println("s.y = " + s.y);
}
} Amphi 4 24
Méthodes statiques (3)
class Test {
static void main() {
Paire s = new Paire();
Paire t = new Paire();
t.x = 2; t.y = 3;
s.affiche_x(); s.affiche_y();
Paire.affiche2_x();
s.affiche2_x();
Paire.affiche3_y(s);
} // s.affiche3_y(s) serait maladroit }
Amphi 4 25
Méthodes statiques (3)
> s.x = 2 // s.affiche_x();
> s.y = 0 // s.affiche_y();
> s.x = 2 // Paire.affiche2_x();
> s.x = 2 // s.affiche2_x();
> s.y = 0 // Paire.affiche3_y();
Amphi 4 26
Méthodes statiques (4)
class Paire {
static int x;
int y;
void affiche_y() { // méthode d'objet System.out.println("s.y = " + this.y);
}
/*static void affiche2_y() {
System.out.println("s.y = " + y);
} Erreur : y n'est pas "static" ! */
}
Files statiques
class File
{ // méthode statique
static void ajouter(int x, File f) {...};
}
class Usage
{ // usage statique File f = new File();
File.ajouter(7, f);
}
Files non statiques
class FileNS
{ // méthode non statique void ajouter(int x) {...};
}
class UsageNS
{ // usage non statique FileNS f = new FileNS();
f.ajouter(7);
}
Amphi 4 29
Plan
• Piqûre de rappel sur les références
• Evaluation d'expressions arithmétiques
• Variables et méthodes statiques
• Vocabulaire sur les arbres
Amphi 4 30
Un arbre de hauteur 4
Racine
Nœuds internes
Feuilles
0
1
2
3
4
Amphi 4 31
Parents, enfants, arité
13 12 11
5 7 8 10
4 2
1
3
6 9
14 15
Le nœud 3 a quatre enfants. C'est un nœud d'arité 4.
Le parent de 5 est 2.
Amphi 4 32
Une définition récursive des arbres Un arbre est un ensemble fini de nœuds, tel que :
(1) Il existe un nœud particulier appelé racine, (2) Les nœuds restants sont partitionnés en ensembles qui sont eux mêmes des arbres.
5 7 8
4 2
1
3
6 9
T = ( 1, { (2, {(5), (6)}),
(3, {(7), (8), (9)}),
(4) } )
Amphi 4 33
Arbres orientés Un arbre orienté est un arbre dans lequel
l'ensemble des enfants de chaque nœud est totalement ordonné.
Exemple : la table des matières d'un livre.
1.1 2.1 2.2
3
1 2
1.2 2.3
chapitres paragraphes
Amphi 4 34
Arbres binaires Un arbre binaire est une structure de données
définie sur un ensemble fini de nœuds, qui est
• soit vide,
• soit union disjointe d'une racine, d'un arbre binaire appelé sous-arbre gauche, et d'un arbre binaire appelé sous-arbre droit.
Attention ! Un arbre binaire n'est pas simplement un arbre ordonné dont tous les nœuds sont d'arité ! 2
Deux arbres binaires distincts
3 1 7
4
8 2
6
9 5
3 1 7
4
8 2
6
9 5
Les arbres binaires en Java
class Arbre { Arbre filsG;
int contenu;
Arbre filsD;
Arbre(Arbre a, int v, Arbre b) {
filsG = a;
contenu = v;
filsD = b;
} }
Amphi 4 37
Parcours d'arbres binaires
9 10 8
4 5 6 7
2 3
1
Préfixe (CGD) :
1, 2, 4, 8, 9, 5, 10, 3, 6, 7
Postfixe (GDC) :
8, 9, 4, 10, 5, 2, 6, 7, 3, 1 Infixe (GCD) :
8, 4, 9, 2, 10, 5, 1, 6, 3, 7
Amphi 4 38
Parcours en largeur
9 10 8
4 5 6 7
2 3
1
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Amphi 4 39
Parcours préfixe en Java
static void ParcoursPrefixe(Arbre a) {
if (a == null) return;
System.out.print(a.contenu + " ");
ParcoursPrefixe(a.filsG);
ParcoursPrefixe(a.filsD);
}
Amphi 4 40
Parcours infixe et postfixe en Java
static void ParcoursInfixe(Arbre a) { if (a == null) return;
ParcoursInfixe(a.filsG);
System.out.print(a.contenu + " ");
ParcoursInfixe(a.filsD);
}
static void ParcoursPostfixe(Arbre a) { if (a == null) return;
ParcoursPostfixe(a.filsG);
ParcoursPostfixe(a.filsD);
System.out.print(a.contenu + " ");
}
Amphi 4 41
Parcours en itératif En itératif, le parcours préfixe est réalisé à
l'aide d'une pile.
Le parcours en largeur est réalisé à l'aide d'une file.
Amphi 4 42
Parcours préfixe à l'aide d'une pile Empiler la racine;
Tant que la pile n'est pas vide {
afficher le sommet de pile et le supprimer;
empiler le fils droit;
empiler le fils gauche
}
8 9 104 5 6 7
3 2
1
3 2
3 5 4
3 5 9 8
3 5 9
3 5
3 10
3 76 7 1
1 2 4 8 9 5 10 3 6 7
Parcours préfixe itératif (1)
class Pile {
final static int maxP = 50;
int hauteur;
Arbre[] contenu;
Pile() {
hauteur = 0;
contenu = new Arbre[maxP];
}
boolean estVide() { return hauteur == 0;
} }
Parcours préfixe itératif (2)
class Pile { // méthodes d'objet...
// ...
void ajouter(Arbre x) { contenu[hauteur++] = x;
}
Arbre valeur() {
return contenu[hauteur-1];
}
void supprimer() { hauteur--;
} }
Amphi 4 45
Parcours préfixe itératif (3)
static void parcoursPrefixeI(Arbre a) { if (a == null) return;
Pile p = new Pile();
p.ajouter(a);
while (!p.estVide()) { a = p.valeur();
p.supprimer();
System.out.print(a.contenu + " ");
if (a.filsD != null) p.ajouter(a.filsD);
if (a.filsG != null) p.ajouter(a.filsG);
} }
Amphi 4 46
Parcours en largeur à l'aide d'une file
10 9 8
4 5 6 7
3 2
1
Ajouter la racine;
Tant que la file n'est pas vide {
afficher le début de la file et le supprimer;
ajouter le fils gauche;
ajouter le fils droit;
}
1 32
5 4 3
7 6 5 4
9 8 7 6
10987 10987
1098
109 10
5 6
1 2 3 4 5 6 7 8 9 10
Amphi 4 47
Parcours en largeur itératif (1)
class File {
final static int MaxF = 30;
int debut;
int fin;
Arbre[] contenu;
File() { debut = 0;
fin = 0;
contenu = new Arbre[MaxF];
}
static int successeur(int i) { return (i+1) % MaxF;
} }
Amphi 4 48
Parcours en largeur itératif (2)
boolean estVide() { return (debut == fin);
}
Arbre valeur() {
return contenu[debut];
}
void ajouter(Arbre x) { contenu[fin] = x;
fin = successeur(fin);
}
void supprimer() {
debut = successeur(debut);
}
Amphi 4 49
Parcours en largeur itératif (3)
static void parcoursLargeurI(Arbre a) { if (a == null) return;
File f = new File();
f.ajouter(a);
while (!f.estVide()) { a = f.valeur();
f.supprimer();
System.out.print(a.contenu + " ");
if (a.filsG != null) f.ajouter(a.filsG);
if (a.filsD != null) f.ajouter(a.filsD);
} }
Amphi 4 50
Obtention de la forme postfixée (1) On utilise une pile pour obtenir la forme postfixée.
6 3 2 - 1 + / 9 6 - * 2 *
((6 / (3 - 2 + 1)) * (9 - 6) * 2)
Règles On lit l'expression pas à pas. Trois règles
(1) Si on a un entier, on l'affiche.
(2) Si on a (, on l'empile avec priorité 0 (3) Si on a ), on dépile en affichant jusqu'à (.
(4) Si on a un opérateur +, - , *, / :
tant que (priorité du sommet de pile " priorité du caractère) afficher puis effacer le sommet de pile.
Puis empiler le caractère entrant.
Priorité des opérateurs : ) / * + - ( 3 2 2 1 1 0
Obtenir : 6 3 2 - 1 + / 9 6 - * 2 *
((6 / (3 - 2 + 1)) * (9 - 6) * 2)
6 3
0( 00((
0(
0(
0(
0(
2/
0(
0(
2/
0(
0(
0(
2/
0(
0(
0(
2/
0(
1-
0(
0(
2/
0(
1-
0(
0(
2/
0(
1+
2
0(
0(
2/
0(
1+
0(
0(
2/
0( 02(*
0(
2*
0(
0(
2*
0(
0(
2*
0(
1-
0(
2*
0(
1-
0(
2*
0(
2*
0(
2*
0( 0( 2/ 0( 1- 2 1+ 1 3)
3) 2* 0( 9 1- 6 3) 2* 3)