SlideShare una empresa de Scribd logo
1 de 139
Descargar para leer sin conexión
Programmation et Algorithmique


        ´
        Ecole Polytechnique




                             ´
        Jean Berstel et Jean-Eric Pin
Avant-propos

     Ce polycopi´ est utilis´ pour le cours INF 421 intitul´ Les bases de la programmation et de
                  e           e                            e
l’algorithmique. Ce cours fait suite au cours INF 311 Introduction a l’informatique et pr´c`de le
                                                                    `                      e e
cours INF 431 intitul´ Fondements de l’informatique.
                        e
     Ce polycopi´ reprend et d´veloppe les chapitres 10 et 11 du polycopi´ de Robert Cori,
                  e                  e                                         e
Jean-Jacques L´vy et Fran¸ois Morain Les bases de la programmation et de l’algorithmique.
                  e              c
Il fait ´galement suite au polycopi´ de Fran¸ois Morain Les bases de l’informatique et de la
         e                              e       c
programmation. Pour qu’il n’y ait pas confusion avec ce dernier polycopi´, nous avons intitul´
                                                                            e                       e
le nˆtre plus simplement Programmation et algorithmique.
     o
     Comme le lecteur pourra le constater, nous avons suivi pour l’essentiel le canevas des cha-
pitres 10 et 11 du polycopi´ de Robert Cori, Jean-Jacques L´vy et Fran¸ois Morain, en incluant
                               e                              e           c
des applications et des d´veloppements sur certaines variantes. Nous avons aussi insist´, au
                              e                                                               e
d´but, sur le concept de r´f´rence, notion qui se retrouve d’ailleurs, sous le terme de pointeur,
  e                           ee
dans d’autres langages de programmation.
     Le th`me principal du cours est, du cˆt´ de la programmation, la conception et la mise
           e                                   oe
en œuvre de nouveaux types. Le langage Java le permet de deux fa¸ons, par la cr´ation de
                                                                         c               e
tableaux, et par la d´finition de classes. Quant a l’algorithmique, c’est la description et l’emploi
                       e                           `
de structures de donn´es dynamiques qui sont au centre de ce cours. Nous traitons en d´tail
                          e                                                                    e
les listes et les arbres. Leur usage dans la repr´sentation de s´quences et d’ensembles ordonn´s
                                                  e             e                                  e
est particuli`rement d´velopp´. Les applications concernent la gestion des partitions (« union-
               e          e        e
find » en anglais), la compression de textes, les t´trarbres (« quadtrees ») et des probl`mes
                                                      e                                       e
g´om´triques qui ne sont pas tous d´crits dans cette premi`re version du polycopi´. Les structures
  e e                                  e                   e                      e
plus ´labor´es, comme les graphes, seront ´tudi´es dans le cours 431.
       e     e                                e    e
     Nous tenons a remercier en tout premier lieu Robert Cori, Jean-Jacques L´vy et Fran¸ois
                    `                                                              e            c
Morain qui nous ont autoris´ a reprendre a notre compte certains ´l´ments de leurs polycopi´s.
                                 e`          `                       ee                           e
                                    e      ´
Nous remercions aussi nos coll`gues de l’ Ecole Polytechnique, et plus particuli`rement Philippe
                                                                                 e
                                                                            ´
Chassignet, Emmanuel Coquery, Fabrice Le Fessant, Laurent Mauborgne, Eric Schost, Alexandre
Sedoglavic et Nicolas Sendrier qui ont largement contribu´ a l’´laboration et a la mise au point
                                                            e` e                `
de ce cours. Enfin nous sommes particuli`rement reconnaissants a Catherine Bensoussan et au
                                            e                      `
                                  ´
service de reprographie de l’Ecole Polytechnique pour leur travail exemplaire.
     Les auteurs peuvent ˆtre contact´s par courrier ´lectronique aux adresses suivantes :
                            e            e            e

                               berstel@univ-mlv.fr
                               Jean-Eric.Pin@liafa.jussieu.fr

On peut aussi consulter les pages Web des auteurs :

                           http : //www-igm.univ-mlv.fr/~berstel
                           http : //liafa.jussieu.fr/~jep




                                                 3
Table des mati`res
              e

I   Compl´ments de programmation
          e                                                                                                                                                9
     1 R´f´rences . . . . . . . . . . . . .
        ee                                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    9
        1.1 Types et r´f´rences . . . .
                        ee                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .    9
        1.2 R´f´rences d’objets . . . .
               ee                             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   12
        1.3 Constructeurs . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   14
     2 M´thodes et variables statiques .
         e                                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17
        2.1 Variables statiques . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   17
        2.2 M´thodes statiques . . . .
                e                             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   19
     3 M´thodes et variables final . . . .
         e                                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   21
     4 La classe String . . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   21

II Structures s´quentielles
                 e                                                                                                                                        25
    1 Listes chaˆ ees . . . . . . . . . . . . . . . . .
                 ın´                                                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   26
        1.1 D´finitions . . . . . . . . . . . . . . .
               e                                                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   26
        1.2 Fonctions simples . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   29
        1.3 Op´rations . . . . . . . . . . . . . . .
                 e                                                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   30
               Copie . . . . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   30
               Recherche . . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   30
               Suppression . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   31
               Concat´nation . . . . . . . . . . . .
                      e                                               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   33
               Inversion . . . . . . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   35
        1.4 Une application : les polynˆmes . . .
                                           o                          .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   36
    2 Listes circulaires . . . . . . . . . . . . . . . .              .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
        2.1 D´finitions . . . . . . . . . . . . . . .
               e                                                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   41
        2.2 Op´rations . . . . . . . . . . . . . . .
                 e                                                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
               Parcours . . . . . . . . . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   43
               Fusion . . . . . . . . . . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
        2.3 Exemples . . . . . . . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
               Permutations . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   45
    3 Variations sur les listes . . . . . . . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   47
    4 Hachage . . . . . . . . . . . . . . . . . . . .                 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   47
        4.1 Adressage direct . . . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   48
        4.2 Tables de hachage . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   48
        4.3 R´solution des collisions par chaˆ
               e                                 ınage                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   49
        4.4 Adressage ouvert . . . . . . . . . . . .                  .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   51
        4.5 Choix des fonctions de hachage . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   52

                                                      5
6                                                                                              `
                                                                                 TABLE DES MATIERES

III Piles et files                                                                                                                 55
     1 Piles . . . . . . . . . . . . . . . . . . . . .   . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    56
          1.1 Implantation . . . . . . . . . . . . .     . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    56
     2 Les exceptions . . . . . . . . . . . . . . . .    . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    60
          2.1 Syntaxe des exceptions . . . . . . .       . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    61
          2.2 Lev´e d’exceptions . . . . . . . . . .
                  e                                      . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    62
          2.3 Capture des exceptions . . . . . . .       . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    62
     3 Une application : l’´valuation d’expressions
                           e                             arithm´tiques .
                                                                 e           .   .   .   .   .   .   .   .   .   .   .   .   .    64
     4 Files . . . . . . . . . . . . . . . . . . . . .   . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    66
          4.1 Implantation . . . . . . . . . . . . .     . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    66
                Implantation par tableaux . . . . .      . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    66
                Implantation par listes chaˆ ees . .
                                             ın´         . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    69
                Choix de l’implantation . . . . . .      . . . . . . . . .   .   .   .   .   .   .   .   .   .   .   .   .   .    70

IV Arbres                                                                                                                         73
    1 D´finitions . . . . . . . . . . . . . . . . . . . . . . . . . . .
        e                                                                    .   .   .   .   .   .   .   .   .   .   .   .   .    73
       1.1 Graphes . . . . . . . . . . . . . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .    73
       1.2 Arbres libres . . . . . . . . . . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .    74
       1.3 Arbres enracin´s . . . . . . . . . . . . . . . . . . . .
                             e                                               .   .   .   .   .   .   .   .   .   .   .   .   .    74
       1.4 Arbres ordonn´s . . . . . . . . . . . . . . . . . . . .
                             e                                               .   .   .   .   .   .   .   .   .   .   .   .   .    75
    2 Union-Find, ou gestion des partitions . . . . . . . . . . . .          .   .   .   .   .   .   .   .   .   .   .   .   .    75
       2.1 Une solution du probl`me . . . . . . . . . . . . . . .
                                     e                                       .   .   .   .   .   .   .   .   .   .   .   .   .    75
       2.2 Applications de l’algorithme Union-Find . . . . . .               .   .   .   .   .   .   .   .   .   .   .   .   .    79
    3 Arbres binaires . . . . . . . . . . . . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .    79
       3.1 Compter les arbres binaires . . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .    80
       3.2 Arbres binaires et mots . . . . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .    80
              Mots . . . . . . . . . . . . . . . . . . . . . . . . . .       .   .   .   .   .   .   .   .   .   .   .   .   .    81
              Ordres sur les mots . . . . . . . . . . . . . . . . . .        .   .   .   .   .   .   .   .   .   .   .   .   .    81
              Codage des arbres binaires . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .    81
       3.3 Parcours d’arbre . . . . . . . . . . . . . . . . . . . .          .   .   .   .   .   .   .   .   .   .   .   .   .    81
       3.4 Une borne inf´rieure pour les tris par comparaisons
                            e                                                .   .   .   .   .   .   .   .   .   .   .   .   .    83
    4 Files de priorit´ . . . . . . . . . . . . . . . . . . . . . . . .
                      e                                                      .   .   .   .   .   .   .   .   .   .   .   .   .    84
       4.1 Tas . . . . . . . . . . . . . . . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .    85
       4.2 Implantation d’un tas . . . . . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .    85
       4.3 Arbres de s´lection . . . . . . . . . . . . . . . . . . .
                          e                                                  .   .   .   .   .   .   .   .   .   .   .   .   .    89
    5 Codage de Huffman . . . . . . . . . . . . . . . . . . . . . .           .   .   .   .   .   .   .   .   .   .   .   .   .    90
       5.1 Compression des donn´es . . . . . . . . . . . . . . .
                                      e                                      .   .   .   .   .   .   .   .   .   .   .   .   .    90
       5.2 Algorithme de Huffman . . . . . . . . . . . . . . . .              .   .   .   .   .   .   .   .   .   .   .   .   .    91
              Codes pr´fixes et arbres . . . . . . . . . . . . . . .
                        e                                                    .   .   .   .   .   .   .   .   .   .   .   .   .    91
              Construction de l’arbre . . . . . . . . . . . . . . .          .   .   .   .   .   .   .   .   .   .   .   .   .    92
              Choix de la repr´sentation des donn´es . . . . . . .
                                e                     e                      .   .   .   .   .   .   .   .   .   .   .   .   .    94
              Implantation . . . . . . . . . . . . . . . . . . . . .         .   .   .   .   .   .   .   .   .   .   .   .   .    94
       5.3 Algorithme de Huffman adaptatif . . . . . . . . . .                .   .   .   .   .   .   .   .   .   .   .   .   .    97

V Arbres binaires                                                                                                                101
   1 Implantation des arbres binaires . . . . . . . . . . . . . . . .            .   .   .   .   .   .   .   .   .   .   .   .   101
      1.1 Implantation des arbres ordonn´s par arbres binaires
                                           e                                     .   .   .   .   .   .   .   .   .   .   .   .   104
   2 Arbres binaires de recherche . . . . . . . . . . . . . . . . . .            .   .   .   .   .   .   .   .   .   .   .   .   105
      2.1 Recherche d’une cl´ . . . . . . . . . . . . . . . . . . .
                               e                                                 .   .   .   .   .   .   .   .   .   .   .   .   106
      2.2 Insertion d’une cl´ . . . . . . . . . . . . . . . . . . . .
                             e                                                   .   .   .   .   .   .   .   .   .   .   .   .   107
`
TABLE DES MATIERES                                                                                                                                       7

         2.3 Suppression d’une cl´ . . . . . . . . . . . . .
                                    e                                              .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   108
         2.4 Hauteur moyenne . . . . . . . . . . . . . . .                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   111
    3   Arbres ´quilibr´s . . . . . . . . . . . . . . . . . . .
               e       e                                                           .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   112
         3.1 Arbres AVL . . . . . . . . . . . . . . . . . .                        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   112
                Rotations . . . . . . . . . . . . . . . . . . .                    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   114
                Implantation des rotations . . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   115
                Insertion et suppression dans un arbre AVL                         .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   115
                Implantation : la classe Avl . . . . . . . . .                     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   116
         3.2 B-arbres et arbres a-b . . . . . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   118
                Arbres a-b . . . . . . . . . . . . . . . . . . .                   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   119
                Insertion dans un arbre a-b . . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   120
                Suppression dans un arbre a-b . . . . . . . .                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   120

VI Applications                                                                                                                                        123
    1 Recherche dans un nuage de points        .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   123
        1.1 Construction de l’arbre . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   123
        1.2 Recherche de points . . . . .      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   125
    2 T´trarbres . . . . . . . . . . . . . .
        e                                      .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   126
    3 Le probl`me des N corps . . . . . .
              e                                .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   128
        3.1 Donn´es . . . . . . . . . . . .
                 e                             .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   129
        3.2 Vecteurs . . . . . . . . . . .     .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   129
        3.3 Corps . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   131
        3.4 Arbre . . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   131
        3.5 Calcul des forces . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   133
        3.6 Univers . . . . . . . . . . . .    .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   135

Bibliographie                                                                                                                                          136

Index                                                                                                                                                  137
Chapitre I

Compl´ments de programmation
     e

    Ce premier chapitre nous permettra de pr´ciser certains points cruciaux de la programmation
                                             e
en Java. Une premi`re section est consacr´e a l’´tude d´taill´e des r´f´rences, ou adresses. La
                    e                      e ` e         e    e        ee
seconde section fait le point sur les m´thodes et les variables statiques. Nous terminons par
                                        e
quelques rappels sur les m´thodes et les variables d´clar´s final.
                          e                         e    e


1     R´f´rences
       ee
    L’utilisation des adresses se retrouve dans divers langages de programmation (Pascal, C,
C++, Java, etc.) et peut paraˆ   ıtre un peu d´routante au d´but. Elle devient limpide d`s que
                                               e              e                           e
l’on en a assimil´ les principes de base et c’est la raison pour laquelle nous y consacrons cette
                  e
section.

1.1   Types et r´f´rences
                ee
    En Java, les donn´es d’un programme se r´partissent en deux cat´gories selon leur type :
                         e                          e                       e
les types primitifs et les autres. Les types primitifs comprennent les types d’entiers (byte, short,
int, long), les types des r´els (float, double), le type des caract`res (char) et le type des bool´ens
                            e                                     e                              e
(boolean). Les autres types sont les types de tableaux ou d’objets. Par exemple, String est un type
d’objets, et int[] est le type d’un tableau d’entiers. La construction de tableaux et la d´finition
                                                                                             e
de nouvelles classes sont les deux moyens de cr´er de nouveaux types a partir de types donn´s.
                                                    e                      `                       e
Ainsi, une d´finition comme
              e
      class Personne
      {
        String nom;
        int age;
      }
d´finit un nouveau type d’objets. Ces deux m´canismes s’emboˆ
 e                                         e               ıtent. Ainsi,
      class Annuaire
      {
        Personne[] liste;
      }
d´finit un type d’objets ayant pour membres un tableau d’objets de type Personne.
 e
   La manipulation des donn´es dans un programme Java d´pend de leur type. La r´f´rence
                              e                               e                          ee
d’une donn´e est l’adresse m´moire o` est log´e la donn´e. La nature pr´cise de l’adresse (entier,
           e                e       u        e         e               e
mani`re de num´roter, etc) nous int´resse peu. Une r´f´rence est de plus typ´e par le type de la
    e          e                   e                 ee                      e
donn´e.
    e

                                                 9
10                                                     ´
                                      CHAPITRE I. COMPLEMENTS DE PROGRAMMATION

R`gle. Les donn´es de type primitif sont manipul´es par valeur, les donn´es des autres types
  e             e                               e                       e
sont manipul´es par r´f´rence.
            e        ee
    Ainsi, le contenu d’une variable de type int est un entier, le contenu d’une variable de type
char est un caract`re, et plus g´n´ralement le contenu d’une variable de type primitif est une
                    e            e e
valeur de ce type. En revanche, le contenu d’une variable de type non primitif est l’adresse d’une
donn´e de ce type. La manipulation de r´f´rences est bien plus limit´e que la manipulation de
      e                                   ee                           e
types de base : on peut seulement les comparer (par == et !=) et les affecter. L’affectation est
une affectation de r´f´rences, et il n’y a donc pas de copie des donn´es r´f´renc´es ! On peut
                      ee                                                 e     ee    e
illustrer ce ph´nom`ne par un exemple concret. Si un ami vous annonce son d´m´nagement et
               e     e                                                            e e
vous donne ses nouvelles coordonn´es, une simple modification dans votre carnet d’adresses vous
                                   e
permettra de continuer a lui ´crire ou a lui t´l´phoner. Bien entendu, cette modification n’a pas
                         `   e         `      ee
eu pour effet le d´m´nagement ou le changement de la ligne t´l´phonique de votre ami. C’est
                   e e                                           ee
la mˆme chose en Java. Lorsqu’on modifie une r´f´rence, cela n’entraˆ pas le d´placement
      e                                             ee                     ıne         e
physique des donn´es, qu’il faudra donc r´aliser ind´pendamment si on le souhaite.
                    e                      e         e
    Voici un premier exemple.
      public static void main(String[] args)
      {
        byte[] t = {5, 2, 6};
        System.out.println("Tableau " + t) ;
      }
Le r´sultat est
    e
      > Tableau [B@f12c4e
La deuxi`me chaˆ s’interpr`te comme suit : les deux premiers caract`res repr´sentent le type
          e       ıne         e                                          e        e
d’un tableau d’octets (le crochet ouvrant [ signifie « tableau » et B signifie « octet’)’, le symbole
’@’ signifie « adresse », la fin est l’adresse en hexad´cimal.
                                                     e
Remarque. (Cette remarque peut ˆtre ignor´e en premi`re lecture) Lors d’une impression, la m´thode
                                       e        e            e                                      e
println cherche une repr´sentation des donn´es sous la forme d’une chaˆ de caract`res. Celle-ci est fournie
                         e                 e                           ıne        e
par la m´thode toString qui est d´finie pour tout objet. Par d´faut, cette m´thode retourne une chaˆ de
          e                       e                             e           e                         ıne
caract`res form´e du nom de la classe, de ’@’ et de l’´criture hexad´cimale du code de hachage de l’objet.
       e         e                                    e             e
Par d´faut, le code de hachage d’un objet est obtenu en hachant l’adresse de l’objet. Dans notre exemple,
      e
f12c4e est l’´criture hexad´cimale du code de hachage de l’adresse du tableau t. Fr´quemment, une classe
             e             e                                                       e
red´finit la m´thode toString. Par exemple, la classe String d´finit cette m´thode pour qu’elle retourne la
    e          e                                                e          e
chaˆ de caract`res contenue dans la donn´e. Ainsi, la chaˆ ”Tableau ” est effectivement affich´e telle
    ıne            e                         e                 ıne                                  e
quelle.
   Une figure bien choisie aide beaucoup a la compr´hension du comportement des r´f´rences.
                                             `           e                               ee
Pour ce faire, la valeur associ´e a une variable n est dessin´e dans une boˆ ´tiquet´e par n.
                               e `                              e                ıte e   e
Dans la figure 1.1, on repr´sente une variable enti`re n dont la valeur est 2. Quand la valeur
                            e                          e
d’une variable est une r´f´rence, c’est-`-dire l’adresse d’une donn´e, la valeur num´rique de cette
                        ee              a                          e                   e
adresse est remplac´e par une fl`che dirig´e vers l’emplacement de la donn´e.
                    e            e          e                                  e



                                                n   2


                          Fig. 1.1 – Une variable n contenant la valeur 2.

    Dans la figure 1.2, on repr´sente une variable de tableau d’octets t. La valeur de cette variable
                              e
est le d´but de la zone m´moire r´serv´e au tableau d’octets.
        e                 e       e    e
´ ´
1. REFERENCES                                                                                            11



         t @f12c4e          @f12c4e       5        2       6           t                     5   2   6

                               (a)                                                       (b)


Fig. 1.2 – Une variable t contenant l’adresse d’un tableau de trois octets : (a) situation effective,
(b) description symbolique.

   Quand une variable vaut null, cette valeur est indiqu´e par une petite croix, comme dans la
                                                        e
figure 1.3.



                                                               t


                            Fig. 1.3 – Une variable t contenant la valeur null.

   Comme nous l’avons dit, les op´rations sur les adresses sont restreintes. Voici un exemple
                                 e
d’affectation.
      public static void main(String[] args)
      {
        byte[] t = {5, 2, 6};
        byte[] s;
        s = t;
        System.out.println("Tableau " + t + " " + s) ;
      }
Le r´sultat est
    e
      > Tableau [B@f12c4e [B@f12c4e
Avant l’affectation s = t, la valeur de s est ind´finie. Apr`s l’affectation, les variables d´signent
                                                e         e                               e
le mˆme emplacement dans la m´moire (voir figure 1.4).
    e                            e


                   t                 5         2       6           t       5         2   6

                   s                                               s

                                         (a)                                   (b)


                       Fig. 1.4 – (a) avant affectation ; (b) apr`s affectation.
                                                                e

     En effet, l’instruction d’affectation s = t copie le contenu de t dans s comme toute affectation,
et le contenu est l’adresse du tableau.
     Continuons notre exploration. En toute logique, puisque apr`s l’affectation s = t, les variables
                                                                   e
s et t d´signent le mˆme emplacement m´moire, toute modification peut ˆtre faite indistinctement
        e             e                   e                                 e
via s ou t. En particulier, une modification via s se rep`re aussi via t. Le programme
                                                           e
      public static void main(String[] args)
12                                                    ´
                                     CHAPITRE I. COMPLEMENTS DE PROGRAMMATION

      {
          byte[] t = {5, 2, 6};
          byte[] s = t;
          s[1] = 8;
          System.out.println(t[1]) ;
      }
affiche en effet le nombre 8.
   A contrario, si l’on recopie les valeurs contenues dans le tableau t dans un autre tableau, les
donn´es sont s´par´es.
    e         e e
      public static void main(String[] args)
      {
        byte[] t = {5, 2, 6};
        byte[] s = new byte[3];
        for (int i = 0; i < t.length; i++)
          s[i] = t[i];
        System.out.println(s + " " + t) ;
        System.out.println(s == t) ;
      }
donne
      > [B@f12c4e [B@93dee9
      > false
En effet, avant la boucle for, le tableau s ne contient que des valeurs nulles (figure 1.5).


                   t           5         2   6       t            5         2   6

                   s           0         0   0       s            5         2   6

                                   (a)                                (b)


                           Fig. 1.5 – (a) avant copie ; (b) apr`s copie.
                                                               e

1.2     R´f´rences d’objets
         ee
    Ce qui a ´t´ illustr´ sur des tableaux s’applique aussi aux objets, d´finis comme instances
             ee         e                                                e
de classes. Reprenons la classe des « personnes » d´j` introduite plus haut.
                                                    ea
      class Personne
      {
        String nom;
        int age;
      }
On s’en sert comme dans la m´thode suivante.
                            e
      public static void main(String[] args)
      {
        Personne p = new Personne();
        p.nom = "Dominique";
        p.age = 22;
        System.out.println(p);
´ ´
1. REFERENCES                                                                                  13

         System.out.println(p.nom + ", " + p.age + " ans");
       }
avec le r´sultat
         e
       > Personne@cac268
       > Dominique, 22 ans
La premi`re ligne affich´e est le contenu de p qui est une r´f´rence ; cette r´f´rence est retourn´e
          e              e                                 ee               ee                  e
par l’instruction new Personne(). La deuxi`me ligne donne le contenu des champs de l’objet dont
                                            e
p contient la r´f´rence. L’objet cr´´ par le programme est repr´sent´ dans la figure 1.6, avant et
               ee                  ee                          e     e
apr`s remplissage.
   e



                              nom age                            nom age
                  p                   0              p                  22

                                                                      Dominique


       Fig. 1.6 – Personne cr´´e par new Personne(), et apr`s remplissage des champs.
                             ee                            e

    Comme d´j` dit plus haut, null est une valeur de r´f´rence particuli`re. Ce n’est la r´f´rence
             ea                                        ee                e                ee
d’aucun objet. On peut affecter null a toute variable r´f´rence, mais aucun champ et aucune
                                       `                 ee
m´thode d’objet n’est accessible par une variable qui contient cette valeur sp´ciale. Une telle
  e                                                                               e
tentative provoque la lev´e d’une exception de la classe NullPointerException.
                         e
    L’op´rateur new est utilis´ pour la cr´ation d’un nouvel objet.
        e                     e           e
  e      `
R`gle. A la cr´ation, les champs d’un objet sont initialis´s a une valeur par d´faut. Cette valeur
               e                                          e `                  e
est 0 pour les types primitifs num´riques, false pour le type bool´en, et null pour tout champ
                                   e                                e
objet.
    Et en effet, le programme
       public static void main(String[] args)
       {
         Personne p = new Personne();
         System.out.println(p + " nom: " + p.nom + ", age: " + p.age);
       }
affiche
       > Personne@93dee9 nom: null, age: 0
Compliquons un peu. Nous avons dit que les deux op´rations de cr´ations de nouveaux types sont
                                                    e              e
les classes et les tableaux. Cr´ons donc un tableau de trois personnes. L` ´galement, le tableau
                               e                                           ae
contient, au d´part, des valeurs par d´faut, donc null puisqu’il s’agit d’un tableau d’objets.
                e                      e
       public static void main(String[] args)
       {
         Personne[] t = new Personne[3];
         Personne p = new Personne();
         p.nom = "Dominique";
         p.age = 22;
         t[1] = p;
         for (int i = 0; i < t.length; i++)
            System.out.print(t[i] + " ");
       }
14                                                  ´
                                   CHAPITRE I. COMPLEMENTS DE PROGRAMMATION

Le r´sultat est
    e
      > null Personne@93dee9 null
La situation est d´crite dans la figure 1.7.
                  e

                             t                   nom age
                                                        22

                                                       Dominique

                                     p


Fig. 1.7 – Tableau de trois personnes. La deuxi`me entr´e est affect´e par copie de la valeur de
                                               e       e           e
p.


1.3   Constructeurs
    Une classe Java est un bloc d’un programme. Une classe d´finit un nouveau type non primitif,
                                                                e
et peut contenir
    – des attributs (aussi appel´s variables),
                                   e
    – des m´thodes,
             e
    – des initialisations,
    – d’autres classes (classes internes ou imbriqu´es).
                                                     e
Parmi les m´thodes, nous connaissons les m´thodes de classe, ou m´thodes statiques (justement
             e                                 e                       e
celles qualifi´es static) et les m´thodes d’instance. Les constructeurs sont d’autres m´thodes qui
              e                   e                                                   e
permettent de cr´er des objets tout en affectant aux champs des valeurs. Leur syntaxe est un
                   e
peu particuli`re. Un constructeur
               e
    – a le mˆme nom que la classe,
              e
    – est sans type de retour (pas mˆme void !).
                                        e
Un constructeur est appel´ par new. Un constructeur particulier, appel´ constructeur par d´faut,
                             e                                            e                 e
est fourni a toute classe : c’est le constructeur sans arguments, celui que nous avons utilis´
            `                                                                                   e
jusqu’alors. Il initialise tous les champs de l’objet cr´´ a leur valeur par d´faut.
                                                        ee `                  e
    Plusieurs constructeurs peuvent coexister. Ceci est dˆ a la possibilit´ de surcharger un nom
                                                             u`             e
de m´thode : deux m´thodes sont surcharg´es (ou l’une est une surcharge de l’autre), si elles ont
      e                 e                    e
le mˆme nom, mais diff`rent par le nombre ou par le type de leurs arguments.
     e                     e
    Reprenons la classe Personne. Le constructeur par d´faut initialise nom a null et age a 0.
                                                             e                    `           `
Voici une nouvelle implantation, avec deux autres constructeurs :
      class Personne
      {
        String nom;
        int age;
        Personne() {}
        Personne(String n, int a)
        {
          nom = n;
          age = a;
        }
´ ´
1. REFERENCES                                                                                 15

         Personne(String n)
         {
           nom = n;
         }
     }
Le programme
     public static void main(String[] args)
     {
       Personne p = new Personne("Luc", 23);
       Personne q = new Personne("Anne");
       System.out.println(p.nom + ", " + p.age + " ans.");
       System.out.println(q.nom + ", " + q.age + " ans.");
     }
affiche
     > Luc, 23 ans.
     > Anne, 0 ans.
Notons que le constructeur par d´faut cesse d’ˆtre fourni implicitement d`s qu’un autre construc-
                                  e           e                           e
teur est d´fini. Si l’on veut quand mˆme disposer de ce constructeur, il faut le red´finir — comme
          e                         e                                              e
nous l’avons fait.
   Voici un autre exemple. Nous manipulons un ensemble de personnes au moyen d’un annuaire,
o` on peut ajouter des personnes, en enlever, et demander si une personne y figure. La classe
 u
Annuaire est form´e d’un tableau de Personne et d’un entier n qui donne la taille de l’annuaire.
                   e
     class Annuaire
     {
       final static int nMax = 12;
       Personne[] liste = new Personne[nMax];
       int n = 0;
       ...
     }
La constante nMax sert a donner une taille maximale. Les m´thodes a d´finir sont
                       `                                  e       ` e
     class Annuaire
     {
       ...
       boolean ajouter(String nom, int age) {...}
       boolean enlever(String nom) {...}
       int index(String nom) {...}
       boolean estDans(String nom) {...}
       void afficher() {...}
     }
On peut s’en servir dans un programme comme
     public static void main(String[] args)
     {
       Annuaire a = new Annuaire();
       a.ajouter("Luc", 22);
       a.ajouter("Anne", 21);
       a.afficher();
       System.out.println();
16                                                ´
                                 CHAPITRE I. COMPLEMENTS DE PROGRAMMATION

          boolean x = a.estDans("Luc"); // retourne true
          a.enlever("Luc");
          a.afficher();
      }
et le r´sultat est
       e
      > Luc, 22 ans.
      > Anne, 21 ans.
      >
      > Anne, 21 ans.
La m´thode index retourne l’entier i tel que liste[i] a pour champ nom l’argument pass´ en
      e                                                                                   e
param`tre, si un tel entier existe, et −1 sinon. Les m´thodes ajouter et enlever retournent un
       e                                               e
bool´en qui indique si l’op´ration a r´ussi.
    e                      e          e
      class Annuaire
      {
        final static int nMax = 12;
        Personne[] liste = new Personne[nMax];
        int n = 0;
          boolean ajouter(String nom, int age)
          {
            if (estDans(nom) || n == nMax)
              return false;
            liste[n++] = new Personne(nom, age);
            return true;
          }
          boolean enlever(String nom)
          {
            int i = index(nom);
            if (i == -1)
              return false;
            for (int j = i + 1; j < n; j++)
              liste[j - 1] = liste[j];
            n--;
            return true;
          }
          int index(String nom)
          {
            for (int i = 0; i < n; i++)
              if (liste[i].nom.equals(nom))
                return i;
            return -1;
          }
          boolean estDans(String nom)
          {
            return (index(nom) != -1);
          }
          void afficher()
          {
´
2. METHODES ET VARIABLES STATIQUES                                                               17

              for (int i = 0; i < n; i++)
              {
                Personne p = liste[i];
                System.out.println(p.nom + ", " + p.age + " ans.");
              }
          }
      }
Ce programme, comme beaucoup d’autres semblables, doit traiter le probl`me de l’adjonction
                                                                               e
d’un ´l´ment a un tableau qui est d´j` plein. La politique de l’autruche consiste a ignorer ce
       ee       `                       ea                                             `
cas. Plus s´rieusement, on peut consid´rer deux solutions : traiter le probl`me, ou le signaler.
            e                             e                                    e
Pour signaler le probl`me, on utilise la m´thode ci-dessus : on ne fait pas l’adjonction, et on
                         e                    e
retourne la valeur false. Une version plus sophistiqu´e, bas´e sur les exceptions, sera d´crite plus
                                                      e     e                            e
loin. Pour traiter le probl`me du tableau plein, il n’y a gu`re qu’une solution : augmenter sa
                             e                                e
taille. Ceci se fait en dupliquant le tableau dans un tableau plus grand, comme d´crit ci-dessous
                                                                                    e
(la m´thode est a inclure dans la classe Annuaire) :
       e           `
          void doublerListe()
          {
            Personne[] nouvelleListe = new Personne[2*liste.length];
            for (int i = 0; i < liste.length; i++)
              nouvelleListe[i] = liste[i];
            liste = nouvelleListe;
          }
Bien voir que l’on recopie le contenu de l’ancien tableau dans le nouveau, puis que l’on copie
l’adresse du nouveau tableau dans la variable contenant l’ancienne adresse. Avec cette m´thode,
                                                                                        e
la m´thode ajouter peut se r´crire de la fa¸on suivante :
     e                      e              c
          boolean ajouter(String nom, int age)
          {
            if (estDans(nom))
              return false;
            if (n == liste.length)
              doublerListe();
            liste[n++] = new Personne(nom, age);
            return true;
          }
En fait, il est si souvent n´cessaire de recopier des tableaux qu’il existe une m´thode toute prˆte
                            e                                                    e              e
propos´e par Java (voir la m´thode System.arraycopy()). De plus, Java dispose de classes qui
       e                         e
g`rent des tableaux dont la taille augmente automatiquement en cas de besoin.
 e


2     M´thodes et variables statiques
       e
    Comme pour les r´f´rences, la distinction entre m´thodes (ou variables) statiques et non
                       ee                               e
statiques ne pr´sente plus de difficult´ si on a assimil´ les principes de bases.
               e                     e                e

2.1   Variables statiques
    Une variable d´clar´e static est commune a tous les objets de la classe. Pour cette raison,
                   e    e                       `
on parle de variable de classe et on peut l’utiliser avec la syntaxe NomdeClasse.nomDeVariable.
Par exemple, dans Math.Pi, Pi est une variable final static de la classe Math. En revanche, une
variable non statique aura une instance par objet. Une variable statique peut aussi ˆtre manipul´e
                                                                                    e           e
18                                                   ´
                                    CHAPITRE I. COMPLEMENTS DE PROGRAMMATION

a travers un objet de la classe, comme toute variable. Ce faisant, on acc`de toujours a la mˆme
`                                                                        e            `     e
variable.
    Comme une variable statique est attach´e a une classe, et non a un objet, on a la r`gle
                                             e `                       `                    e
essentielle suivante.
R`gle. Toute modification d’une variable statique peut ˆtre faite indistinctement par n’importe
  e                                                      e
quel objet de la classe. Cette modification est visible par tous les objets de la classe.
    Pour illustrer ce ph´nom`ne, consid´rons une classe contenant une variable statique et une
                        e   e          e
variable non statique.
      class Paire
      {
        static int x;
        int y;
      }
On peut alors utiliser la variable statique x, sous la forme Paire.x, sans d´clarer d’objet, mais
                                                                            e
´crire Paire.y provoquerait une erreur. Par contre, si on d´clare un objet s de type Paire, on a
e                                                          e
acc`s aux champs s.x et s.y.
   e
      class Test
      {
        static void main()
        {
          Paire s = new Paire();
          System.out.println("s.x = " + s.x + ", s.y = " + s.y +
                             ", Paire.x = " + Paire.x);
        }
      }
Le r´sultat est
    e
      > s.x = 0, s.y = 0, Paire.x = 0
Modifions l´g`rement la classe Test.
          e e
      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);
        }
      }
Le r´sultat est
    e
      > t.x = 2, t.y = 3
      > s.x = 2, s.y = 0
Comme on le voit, l’instruction t.x = 2 a modifi´ la valeur de la variable statique x. De ce fait, la
                                                 e
valeur retourn´e par s.x est ´galement modifi´e. En revanche, l’instruction t.y = 3 n’a eu aucune
               e             e                e
influence sur la valeur de s.y. Pour clarifier de tels comportements, il est d’ailleurs pr´f´rable de
                                                                                         ee
remplacer l’instruction t.x = 2 par Paire.x = 2. Mˆme s’il y a plusieurs objets de la classe Paire, il
                                                   e
´
2. METHODES ET VARIABLES STATIQUES                                                               19

n’y a qu’une seule instance de la variable statique x. Les expressions Paire.x, s.x et t.x d´signent
                                                                                            e
la mˆme donn´e a la mˆme adresse. Une derni`re pr´cision : a l’int´rieur de la classe Paire, la
     e         e `       e                       e      e        `     e
variable statique Paire.x peut s’´crire plus simplement x, car la classe courante est implicite.
                                 e
    Pour bien illustrer ce qui pr´c`de, voici une l´g`re variation du programme pr´c´dent.
                                 e e               e e                                e e
      class Paire
      {
        static int[] x;
        int y;
      }
      class StaticTest
      {
        public static void main(String[] args)
        {
          Paire.x = new int[1];
          Paire.x[0] = 7;
              System.out.println(
                "Paire.x = " + Paire.x + ", Paire.x[0] = " + Paire.x[0]);
              Paire s = new Paire();
              s.y = 3;
              System.out.println("s.x = " + s.x + ", s.y = " + s.y);
              Paire t = new Paire();
              t.y = 4;
              System.out.println("t.x = " + t.x + ", t.y = " + t.y);
          }
      }
Ce programme affichera
      > Paire.x = [I@93dee9, Paire.x[0] = 7
      > s.x = [I@93dee9, s.y = 3
      > t.x = [I@93dee9, t.y = 4

2.2   M´thodes statiques
       e
    Une m´thode d´clar´e static peut ˆtre utilis´e sans r´f´rence a un objet particulier. On
           e          e     e             e          e         ee        `
parle alors de m´thode de classe. Une m´thode statique n’a pas directement acc`s aux variables
                 e                        e                                        e
non statiques. On peut appeler une m´thode statique par NomdeClasse.nomDeMethode(). Par
                                         e
exemple, dans Math.abs(), abs() est une m´thode statique de la classe Math.
                                             e
    Une m´thode qui n’est pas d´clar´e static est toujours utilis´e en r´f´rence a un objet.
           e                        e    e                             e      ee        `
On parle alors de m´thode d’objet. On peut appeler une m´thode non statique par nomOb-
                        e                                         e
jet.nomDeMethode(). Par exemple, la classe System contient une variable de classe de nom out.
L’objet System.out appelle une m´thode d’objet de nom println().
                                   e
    Pour simplifier l’´criture des m´thodes d’objet, on utilise souvent le mot cl´ this, qui d´signe
                      e             e                                            e            e
l’objet courant. Il n’a jamais la valeur null, et sa valeur ne peut ˆtre modifi´e. Utiliser this dans
                                                                    e         e
une m´thode statique produit une erreur a la compilation.
       e                                    `
    Pour illustrer ces d´finitions, introduisons simultan´ment dans la classe Paire des m´thodes
                          e                                e                                e
de classe et des m´thodes d’objet.
                    e
      class Paire
      {
        static int x;
20                                               ´
                                CHAPITRE I. COMPLEMENTS DE PROGRAMMATION

          int y;

          void affiche_x() // m´thode d’objet
                               e
          {
            System.out.println("s.x = " + this.x);
          }

          void affiche_y() // m´thode d’objet
                               e
          {
            System.out.println("s.y = " + this.y);
          }

          static void affiche2_x() // m´thode de classe
                                       e
          {
            System.out.println("s.x = " + x);
          }

          static void affiche3_y(Paire s)
          {
            System.out.println("s.y = " + s.y);
          }
      }
On remarquera la syntaxe utilisant this dans affiche x et dans affiche y et l’utilisation de la
variable statique x dans affiche2 x. On notera ´galement la diff´rence entre la m´thode sans
                                             e               e                 e
param`tre affiche y et la m´thode affiche3 y qui prend en param`tre un objet s de type Paire.
      e                    e                                 e
Attention en effet au pi`ge suivant :
                       e
      // Attention, cette m´thode est incorrecte ...
                           e
        static void affiche2_y()
        {
          System.out.println("s.y = " + y);
        }
      // ... car y n’est pas "static" !
Maintenant, le programme
      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
      }
produit le r´sultat suivant :
            e
´
3. METHODES ET VARIABLES FINAL                                                                       21

        >   s.x   =   2
        >   s.y   =   0
        >   s.x   =   2
        >   s.x   =   2
        >   s.y   =   0


3    M´thodes et variables final
      e
    La d´claration d’une variable final doit toujours ˆtre accompagn´e d’une initialisation. Une
        e                                            e              e
m´thode final ne peut ˆtre surcharg´e.
  e                   e            e
    Une variable final ne peut ˆtre modifi´e. Attention toutefois ! Si la variable est un tableau,
                              e           e
donc une r´f´rence, cette r´f´rence ne change plus, mais les valeurs du tableau peuvent ˆtre
           ee              ee                                                               e
modifi´es !
      e
        class Test
        {
          static final int n = 100;
          static final int[] a = {1, 2, 3};
            public static void main(String args[])
            {
              a[0] = 5; // OK
              n = 9; // Erreur ! Variable finale
            }
        }
Les m´thodes d’une classe final sont implicitement final. La classe String est une classe final.
     e


4    La classe String
    La manipulation des chaˆ   ınes de caract`res est simplifi´e en Java par la classe String. Cette
                                              e               e
classe, dont nous venons de dire qu’elle est finale, permet les op´rations usuelles sur les chaˆ
                                                                  e                              ınes de
caract`res. Toutefois, les objets de la classe String sont immutables, c’est-`-dire qu’ils ne peuvent
        e                                                                    a
ˆtre modifi´s. Une op´ration sur une chaˆ de caract`re se traduit donc, lors d’une modification,
e             e        e                   ıne           e
par la cr´ation d’un nouvel objet. Dans la suite de ce polycopi´, on parlera souvent d’op´rations
          e                                                       e                            e
destructrices et non destructrices ; dans ce contexte, les op´rations de la classe String sont non
                                                                e
destructrices. Il existe une variante, destructrice, des chaˆ
                                                            ınes de caract`res, la classe StringBuffer.
                                                                          e
    Les m´thodes de la classe String sont nombreuses. Voici quelques-unes des plus fr´quemment
            e                                                                              e
utilis´es :
      e
        int length()
        char charAt(int index)
        String toLowerCase()
        String toUpperCase()
Ainsi
        "abc".charAt(1)
retourne le caract`re b, et
                  e
        "X2001".toLowerCase()
retourne la chaˆ x2001. D’autres m´thodes sont utiles pour la comparaison, l’examen, la mo-
               ıne                  e
dification. En voici quelques exemples :
22                                                   ´
                                    CHAPITRE I. COMPLEMENTS DE PROGRAMMATION

      boolean equals(String s)
      int compareTo(String s)
      boolean startsWith(String prefix)
      boolean endsWith(String suffix)
      int indexOf(String facteur)
      int lastIndexOf(String facteur)
L’´galit´ de deux chaˆ
  e      e             ınes de caract`res se teste par equals. Le test par == teste l’´galit´ des
                                         e                                               e    e
adresses. La classe String est tr`s optimis´e en Java, et souvent les chaˆ
                                  e          e                            ınes compos´es des mˆmes
                                                                                     e        e
caract`res sont en fait rang´es qu’une seule fois en m´moire (ce qui est possible puisqu’elles sont
       e                     e                         e
inmodifiables !). De ce fait, l’´galit´ du contenu implique souvent l’´galit´ des adresses et peut
                                e      e                                e     e
donc ˆtre test´ de cette mani`re.
      e       e                e
    La m´thode compareTo compare la chaˆ avec l’argument, pour l’ordre alphab´tique. Elle
           e                                   ıne                                      e
retourne un entier n´gatif, 0, ou un entier positif selon que la chaˆ appelante est plus petite,
                     e                                                ıne
´gale ou plus grande que la chaˆ pass´e en argument. Ainsi
e                                  ıne     e
      "X2001".compareTo("W1001")
retourne un nombre positif. Bien entendu, compareTo retourne 0 si et seulement si equals retourne
true. La m´thode indexOf (resp. lastIndexOf) retourne le plus petit (resp. plus grand) indice o`
          e                                                                                     u
la chaˆ en argument commence comme facteur de la chaˆ appelante, et -1 si l’argument n’est
      ıne                                                ıne
pas facteur. Ainsi
      "X2000001".indexOf("00")
      "X2000001".lastIndexOf("00")
donne 2 et 5. Enfin, voici quelques op´rations de construction :
                                     e
      String   valueOf(int i)
      String   substring(int debut, int fin)
      String   concat(String s)
      String   replace(char x, char y)
Il existe en fait neuf versions de la m´thode valueOf, qui diff´rent par le type de l’argument
                                           e                         e
(celle cit´e ci-dessus a pour argument un int). Elles retournent toutes une chaˆ de caract`res
          e                                                                           ıne         e
repr´sentant la valeur pass´e en param`tre. La m´thode concat retourne une nouvelle chaˆ de
     e                         e           e          e                                         ıne
caract`res form´e de la chaˆ appelante et de la chaˆ en param`tre. Enfin, notons la possibilit´
        e        e             ıne                       ıne           e                            e
de cr´er un objet de la classe String implicitement, par l’´num´ration de son ´criture. Ainsi, les
      e                                                        e    e               e
chaˆınes comme ”X2000001” sont des objets de la classe String. La m´thode remplace remplace
                                                                           e
toutes les occurrences du caract`re x par le caract`re y. Le mot “remplace” n’est pas tr`s bon,
                                     e                  e                                     e
puis que c’est une nouvelle chaˆ de caract`res qui est cr´e.
                                    ıne          e              e
    Parfois, il est utile de disposer de la suite des caract`res d’un String sous forme d’un tableau.
                                                             e
La m´thode toCharArray() retourne un tel tableau ; r´ciproquement, le constructeur String(char[]
       e                                                  e
tableau) construit une chaˆ a partir d’un tableau de caract`res.
                              ıne `                               e
      char[] tableau = "X2000001".toCharArray();
      tableau[1]++;
      String s = new String(tableau);
La chaˆ retourn´e est bien sˆ r ”X3000001”.
        ıne         e          u
    Retour sur la m´thode toString(). La m´thode toString() fournit une chaˆ de caract`res
                      e                      e                                ıne          e
contenant une description textuelle de l’objet qui l’appelle. Comme nous l’avons dit plus haut,
cette m´thode retourne par d´faut une chaˆ de caract`res form´e du nom de la classe, de
         e                     e             ıne           e       e
’@’ et de l’´criture hexad´cimale du code de hachage de l’objet. Pour les objets d´finis par des
            e             e                                                       e
tableaux, le nom est form´ du pr´fixe [ pour les tableaux, et du codage suivant du nom des
                            e      e
types :
4. LA CLASSE STRING                                                                        23

                    B   byte                    J                  long
                    C   char                    Lnom de classe ;   objet
                    D   double                  S                  short
                    F   float                    Z                  boolean
                    I   int
   Consid´rons l’exemple suivant :
         e
      class Exemple
      {
        public static void main(String[] args)
        {
          Exemple e = new Exemple();
          Exemple[] t = new Exemple[12];
          Exemple[][] u = new Exemple[12][24];
          System.out.println(e) ;
          System.out.println(t) ;
          System.out.println(u) ;
        }
      }
Le r´sultat est :
    e
      > Exemple@7182c1
      > [LExemple;@3f5d07
      > [[LExemple;@fabe9
et en effet, la variable u est un tableau dont les ´l´ments sont des tableaux dont les ´l´ments
                                                  ee                                  ee
sont de type Exemple.
24                    ´
     CHAPITRE I. COMPLEMENTS DE PROGRAMMATION
Chapitre II

Structures s´quentielles
            e

     Les structures de donn´es en algorithmique sont souvent complexes et de taille variable.
                               e
Elles sont souvent aussi dynamiques, au sens o` elles ´voluent, en forme et en taille, en cours
                                                         u         e
d’ex´cution d’un programme. Les tableaux pr´sentent, dans cette optique, un certain nombre
      e                                                 e
de limitations qui en rendent parfois l’usage peu naturel.
     Tout d’abord, un tableau est de taille fixe, d´termin´ a sa cr´ation. Il faut donc choisir une
                                                           e         e`      e
taille suffisante d`s le d´but, ce qui peut amener a un gaspillage consid´rable de place. Et mˆme
                    e     e                                `                     e               e
si l’on a vu large, il arrive que la place manque. Il faut alors proc´der a la cr´ation d’un tableau
                                                                             e   `     e
plus grand et a une recopie, ce qui repr´sente une perte de temps qui peut ˆtre importante.
                 `                              e                                      e
     Un tableau a une structure fixe, lin´aire. Une modification de l’ordre, par exemple par inser-
                                              e
tion d’un ´l´ment, oblige a d´placer d’autres ´l´ments du tableau, ce qui peut ˆtre tr`s coˆ teux.
              ee              ` e                     ee                                  e e  u
Un tableau est donc rigide, et peu ´conomique si l’ensemble des ´l´ments qu’il contient est appel´
                                       e                                   ee                       e
a ´voluer en cours d’ex´cution.
`e                        e
     Dans ce chapitre et dans le chapitre suivant, nous introduisons quelques structures dyna-
miques. Elles sont utilis´es de fa¸on tr`s intensive en programmation. Leur but est de g´rer un
                           e         c        e                                               e
ensemble fini d’´l´ments dont le nombre n’est pas fix´ a priori et peut ´voluer.
                   ee                                           e                  e
     Les structures dynamiques doivent r´pondre a un certain nombre de crit`res. Elles doivent
                                                 e          `                            e
permettre une bonne gestion de la m´moire, par un usage ´conome de celle-ci. Mais elles doivent
                                           e                           e
aussi ˆtre simples a utiliser, pour ne pas ´changer cette ´conomie en m´moire contre une difficult´
        e            `                         e                  e            e                    e
d’emploi, ou un temps d’ex´cution disproportionn´.
                               e                             e
     La solution pr´sent´e ici, et g´n´ralement utilis´e, repose sur trois principes :
                     e    e           e e                     e
     – Allocation de la m´moire au fur et a mesure des besoins. On dispose alors de toute la place
                            e                    `
        n´cessaire sans en gaspiller.
          e
     – D´finition r´cursive des structures. Elle permettent en contrepoint une programmation
          e          e
        simple par des m´thodes elle-mˆmes r´cursives, calqu´es sur leur structure.
                          e                 e       e                    e
     – Enfin, un petit nombre d’op´rateurs d’acc`s et de modification, a partir desquels on
                                          e                  e                       `
        construit des m´thodes plus ´labor´es par composition.
                        e               e         e
Allouer de la m´moire signifie r´server de la m´moire pour l’utilisation du programme. Apr`s
                   e                 e                    e                                        e
utilisation, on peut ensuite d´sallouer cette m´moire. Dans des langages tels que PASCAL ou C,
                                 e                    e
il faut g´rer soigneusement l’allocation et la d´sallocation. En JAVA, c’est un peu plus simple :
           e                                           e
il faut toujours allouer de la m´moire, mais JAVA se charge de d´sallouer la m´moire qui ne sert
                                   e                                        e            e
plus.
     On notera que la description ci-dessus repose sur des principes qui ne d´pendent pas du lan-
                                                                                     e
gage de programmation choisi. En Java, et dans d’autres langages de haut niveau, on peut mˆme    e
sp´cifier une structure dynamique par une description purement abstraite de ses propri´t´s. Ce
   e                                                                                          ee
style de programmation utilisant des types abstraits rel`ve des cours ult´rieurs (cours 431 et
                                                                      e              e
cours de majeure).
     Nous ´tudierons dans ce cours deux types de structures dynamiques. Ce chapitre est consacr´
             e                                                                                      e

                                                 25
26                                                                    ´
                                             CHAPITRE II. STRUCTURES SEQUENTIELLES

aux structures dites s´quentielles : listes, piles et files d’attente. Le chapitre suivant traite des
                       e
arbres et de leur utilisation. D’autres structures dynamiques, en particulier les graphes, sont
trait´es dans le cours « Fondements de l’informatique ».
     e
    Les structures consid´r´es servent a manipuler des ensembles. Les ´l´ments de ces ensembles
                          ee            `                                 ee
peuvent ˆtre de diff´rentes sortes : nombres entiers ou r´els, chaˆ
          e          e                                     e       ınes de caract`res, ou des objets
                                                                                 e
plus complexes comme des processus, des expressions, des matrices. Le nombre d’´l´ments des
                                                                                       ee
ensembles varie au cours de l’ex´cution du programme, par ajout et suppression d’´l´ments en
                                 e                                                      ee
cours de traitement. Plus pr´cis´ment, les op´rations que l’on s’autorise sur un ensemble E sont
                             e e                e
les suivantes :
    – tester si l’ensemble E est vide.
    – ajouter l’´l´ment x a l’ensemble E.
                 ee        `
    – v´rifier si l’´l´ment x appartient a l’ensemble E.
        e          ee                     `
    – supprimer l’´l´ment x de l’ensemble E.
                    ee


1     Listes chaˆ ees
                ın´
    Une liste chaˆn´e est compos´e d’une suite finie de couples form´s d’un ´l´ment et de l’adresse
                    ı e            e                                  e        ee
(r´f´rence) vers l’´l´ment suivant.
  ee                 ee
    Il s’agit d’une structure de base de la programmation, fort ancienne. Un usage syst´matique
                                                                                              e
en est d´j` fait dans le langage Lisp (LISt Processing), con¸u par John MacCarthy en 1960.
          ea                                                     c
Une version plus r´cente de ce langage, Scheme, utilise principalement cette structure. Les listes
                      e
sont aussi pr´d´finies en Caml. Dans la plupart des langages a objets, comme C++ et Java, on
                e e                                              `
trouve des classes g´rant les listes.
                        e
    La recherche d’un ´l´ment dans une liste s’apparente a un classique « jeu de piste » dont le
                           ee                                `
but est de retrouver un objet cach´ : on commence par avoir des informations sur un « site » o`
                                     e                                                                u
pourrait se trouver cet objet. En ce lieu, on d´couvre des informations, et une indication sur un
                                                e
autre site (l’adresse d’un autre site) o` l’objet pourrait se trouver, et ainsi de suite. Le point de
                                        u
d´part du jeu de piste est l’adresse du premier site qu’il faut visiter. Une version contemporaine
 e
de ce jeu consisterait en une suite de pages Web contenant une information et un lien vers la
page suivante. Il y a une analogie ´vidente entre lien et r´f´rence.
                                     e                       ee
    Notons que l’ordre de la suite des ´l´ments d’une liste chaˆ ee n’est pas connu globalement,
                                        ee                        ın´
puisqu’on ne connaˆ que le successeur d’un ´l´ment. C’est ce caract`re local qui permet une
                        ıt                       ee                        e
grande souplesse d’organisation : il suffit de modifier, en un seul site, la r´f´rence au site suivant
                                                                             ee
pour r´organiser la suite des pages Web.
        e
    Les op´rations usuelles sur les listes sont les suivantes :
            e
    – cr´er une liste vide.
          e
    – tester si une liste est vide.
    – ajouter un ´l´ment en tˆte de liste.
                     ee         e
    – rechercher un ´l´ment dans une liste.
                         ee
    – supprimer un ´l´ment dans une liste.
                         ee
D’autres op´rations sont : retourner une liste, concat´ner deux listes, fusionner deux listes, etc.
              e                                          e
    En Java, les « sites » sont des objets qui poss`dent deux champs : un champ pour le contenu,
                                                    e
et un champ qui contient la r´f´rence vers le site suivant. L’acc`s a la liste se fait par la r´f´rence
                               ee                                 e `                           ee
au premier site. Il est de tradition d’appeler cellule ce que nous avons appel´ site.
                                                                                  e

1.1   D´finitions
       e
   Les d´clarations sont les suivantes. On suppose ici que les ´l´ments stock´s dans la liste sont
         e                                                     ee            e
des entiers. Bien entendu, le sch´ma de d´claration serait le mˆme pour une liste de caract`res,
                                 e        e                     e                            e
de bool´ens, ou d’objets de type quelconque.
       e
1. LISTES CHAˆ EES
             IN ´                                                                               27

      class Liste
      {
        int contenu;
        Liste suivant;

          Liste (int x, Liste a)
          {
            contenu = x;
            suivant = a;
          }
      }
Une liste est repr´sent´e par la r´f´rence au premier objet de type Liste. La liste vide, sans
                    e    e           ee
´l´ment, a pour r´f´rence null. La figure 1.1 repr´sente la forme g´n´rale d’une liste. La liste est
ee                 ee                             e               e e
compos´e de cellules. Chacune contient, dans son champ contenu, l’un des ´l´ments de la liste.
         e                                                                   ee
Le champ suivant contient la r´f´rence a la cellule suivante. La croix dans la derni`re cellule
                                  ee       `                                            e
indique que sa valeur est null, convention pour indiquer qu’il n’y a pas d’´l´ment suivant. Une
                                                                           ee
liste est rep´r´e par la r´f´rence a sa premi`re cellule.
             ee           ee       `         e
                                           su nu




                                                        su nu




                                                                                   su nu
                                                  nt




                                                               nt




                                                                                          nt
                                                e
                                             iva



                                                             e
                                                          iva




                                                                                        e
                                                                                     iva
                                             nt




                                                          nt




                                                                                     nt
                                          co




                                                       co




                                                                                 co
                                                                           ¢¢¡
                                                                          ¡ ¡

                               Fig. 1.1 – Forme g´n´rale d’une liste.
                                                 e e

    L’instruction new Liste (x, a) construit une nouvelle cellule dont les champs sont x et a et
retourne la r´f´rence a cette cellule. Revenons a notre jeu de piste. Supposons que l’adresse du
              ee       `                          `
premier site soit a. L’instruction new Liste (x, a) revient a ins´rer, au d´but du jeu, un nouveau
                                                            `    e         e
site, dont le contenu est x. Il contient, comme indication du site suivant, l’adresse de l’ancien
point de d´part, soit a. Le nouveau point de d´part est le site fraˆ
           e                                     e                   ıchement ins´r´.
                                                                                 ee
    Cr´er une liste de trois entiers, par exemple de 2, 7 et 11 se fait par usage r´p´t´ de l’ins-
       e                                                                             e ee
truction d’insertion :
      Liste a = new Liste(2, new Liste (7, new Liste (11, null)))
La liste de cet exemple est repr´sent´e dans la figure 1.2.
                                e    e



                              a            2             7           11


           Fig. 1.2 – Une liste de trois ´l´ments 2, 7, 11 repr´sent´es par trois cellules.
                                         ee                    e    e

    Venons-en aux op´rations sur les listes. La m´thode listeVide retourne une liste vide, c’est-
                    e                            e
a-dire null.
`
      static Liste listeVide ()
      {
        return null;
      }
28                                                                    ´
                                             CHAPITRE II. STRUCTURES SEQUENTIELLES

La fonction qui teste si une liste est vide s’´crit :
                                              e
       static boolean estVide (Liste a)
       {
         return a == null;
       }
Il faut bien dire que ces fonctions sont si simples qu’on les remplace souvent par leur d´finition
                                                                                         e
dans la pratique.
     Ajouter un ´l´ment en d´but de liste se fait par :
                ee           e
       static Liste ajouter (int x, Liste a)
       {
         return new Liste (x, a);
       }
L’effet de cette op´ration est repr´sent´ dans la figure 1.3.
                  e               e    e


                              a                             ¤¢£
                                                           £ £
                              x


                     Fig. 1.3 – Ajout d’un ´l´ment x au d´but d’une liste a.
                                           ee            e

     Ainsi, cr´er une liste contenant seulement x se fait de l’une des quatre fa¸ons ´quivalentes :
              e                                                                 c    e
              new Liste(2, null)                         ajouter(x, null)
              new Liste(2, listeVide())                  ajouter(x, listeVide())
Voici un autre exemple :
       static Liste suite(int n)
       {
         Liste a = null;
         for (int i = n; i >=1; i--)
           a = ajouter(i, a);
         return a;
       }
Cette fonction retourne une liste contenant les entiers de 1 a n, dans cet ordre. Noter le parcours
                                                               `
d´croissant des entiers dans la boucle.
 e
    Deux fonctions d’acc`s sont importantes : celle retournant le contenu, et celle retournant la
                           e
r´f´rence a la suite de la liste. Ces fonctions ne doivent ˆtre appel´es que sur des listes non vides.
 ee       `                                                e         e
       static int tete(Liste a)
       {
         return a.contenu;
       }
       static Liste queue(Liste a)
       {
         return a.suivant;
       }
1. LISTES CHAˆ EES
             IN ´                                                                             29

L` encore, on utilise souvent dans la pratique l’expression plutˆt que la fonction. Les trois
  a                                                                  o
fonctions ajouter, tete et queue sont li´es par les ´quations suivantes.
                                        e           e

                                  tete(ajouter(x, a)) = x
                                queue(ajouter(x, a)) = a
                           ajouter(tete(a), queue(a)) = a;   (a = null)

Elles permettent de simplifier toute expression compos´e de ces trois fonctions en une forme
                                                         e
r´duite.
 e
    Les trois fonctions ajouter, tete et queue permettent de r´aliser beaucoup d’op´rations sur
                                                              e                    e
les listes. Elles ne permettent pas, en revanche, de modifier la valeur d’un champ, que ce soit
le contenu ou la r´f´rence a la cellule suivante. C’est pourquoi on appelle ces fonctions, et
                     ee      `
les op´rations qu’elles permettent de r´aliser, des op´rations non destructives, en opposition
        e                                 e            e
aux op´rations qui modifient la valeur, qui d´truisent donc les valeurs pr´c´dentes, et qui sont
         e                                     e                          e e
appel´es destructives. L’usage d’op´rations non destructives pour modifier une donn´e am`ne a
       e                             e                                              e     e `
la recopie des parties a modifier.
                        `

1.2   Fonctions simples
    Voici quelques exemples de fonctions simples et utiles. Elles sont bas´es sur le parcours des
                                                                           e
´l´ments d’une liste. La longueur d’une liste est le nombre d’´l´ments qui la composent. En voici
ee                                                            ee
une r´alisation :
     e
      static int longueur(Liste a)
      {
        if (estVide(a)) return 0;
        return 1 + longueur(queue(a));
      }
On peut l’´crire de mani`re plus condens´e, en utilisant une expression conditionnelle :
          e             e               e
      static int longueur(Liste a)
      {
        return (estVide(a)) ? 0 : 1 + longueur(queue(a));
      }
On peut aussi l’´crire de mani`re it´rative, et par acc`s direct aux champs :
                e             e     e                  e
      static int longueurI(Liste a)
      {
        int n = 0;
        while (a != null)
        {
          n++;
          a = a.suivant;
        }
        return n;
      }
Autre exemple similaire, l’affichage d’une liste. On choisit ici d’afficher les ´l´ments sur une
                                                                            ee
ligne, s´par´s par un blanc.
        e e
      static void afficher(Liste a)
      {
        if (estVide(a))
          System.out.println();
30                                                                     ´
                                              CHAPITRE II. STRUCTURES SEQUENTIELLES

           else
           {
             System.out.print(a.contenu + " ");
             afficher(a.suivant);
           }
       }
Notons que si les deux derni`res instructions de la m´thode pr´c´dente sont interverties, la liste
                            e                          e        e e
est affich´e dans l’ordre inverse ! Bien sˆ r, on peut ´crire notre fonction de fa¸on it´rative :
        e                               u            e                          c     e
       static void afficherI(Liste a)
       {
         while (a != null)
         {
           System.out.print(a.contenu + " ");
           a = a.suivant;
         }
         System.out.println();
       }

1.3     Op´rations
          e
Copie
     La copie d’une liste est facile a r´aliser. En voici une version r´cursive.
                                     ` e                               e
       static Liste copier(Liste a)
       {
         if (a == null)
           return a;
         return ajouter(tete(a), copier(queue(a));
       }

Recherche
     La recherche d’un ´l´ment dans une liste peut aussi se faire it´rativement et r´cursivement.
                       ee                                           e               e
C’est encore un algorithme bas´ sur un parcours, mais le parcours est interrompu d`s que
                                 e                                                         e
l’´l´ment cherch´ est trouv´. Voici l’´criture it´rative :
  ee             e         e          e          e
       static boolean estDansI(int x, Liste a) // it´ratif
                                                    e
       {
         while (a != null)
         {
           if (a.contenu == x)
             return true;
           a = a.suivant;
         }
         return false;
       }
La boucle while peut ˆtre transform´e de mani`re m´canique en une boucle for. Dans notre cas,
                       e           e         e    e
on obtient l’´criture suivante :
             e
       static boolean estDansI(int x, Liste a) // it´ratif
                                                    e
       {
         for(; a!= null; a = a.suivant)
1. LISTES CHAˆ EES
             IN ´                                                                                    31

           if (a.contenu == x)
             return true;
         return false;
       }
Voici enfin une premi`re version r´cursive. Elle distingue trois cas : une liste vide, o` la recherche
                        e             e                                                  u
´choue, une liste dont la tˆte est l’´l´ment cherch´, o` la recherche r´ussit, et le cas restant, trait´
e                           e         ee            e u                 e                              e
par r´cursion.
      e
       static boolean estDans(int x, Liste a) // r´cursif     e
       {
         if (a == null)
             return false;
         if (a.contenu == x)
             return true;
         return estDans(x, a.suivant);
       }
Voici une deuxi`me version, utilisant a la fois les fonctions d’acc`s et une expression bool´enne :
                  e                      `                          e                           e
       static boolean estDans(int x, Liste a) // r´cursif     e
       {
         return !estVide(a) && (tete(a) == x || estDans(x, queue(a)));
       }
En Java, l’´valuation d’expressions bool´ennes se fait de gauche a droite et est toujours pares-
             e                             e                          `
seuse. Ceci signifie que lors de l’´valuation d’une expression bool´enne du type b1 || b2, o` b1
                                    e                                 e                            u
et b2 sont des expressions bool´ennes, Java ´value d’abord b1. Si le r´sultat de cette ´valuation
                                  e            e                            e                e
est true, il en d´duit que la valeur de b1 || b2 est true, sans mˆme ´valuer b2. Par contre, si le
                  e                                                e      e
r´sultat est false, il poursuit en ´valuant b2. Dans le cas d’une expression du type b1 && b2, le
 e                                  e
mˆme principe paresseux s’applique : si b1 est ´valu´ a false, Java en conclut que b1 && b2 vaut
   e                                              e    e`
false sans ´valuer b2.
            e
     Dans notre cas, le deuxi`me facteur de la conjonction n’est donc pas ´valu´ si la liste est
                               e                                                 e     e
vide. On voit donc l` un int´rˆt subtil de l’´valuation paresseuse, en sus du gain de temps. Si
                        a       ee             e
l’´valuation n’´tait pas paresseuse, comme c’´tait le cas en PASCAL, un des ancˆtres de JAVA,
  e             e                               e                                      e
l’´valuation de tete(a) provoquerait une erreur...
  e

Suppression
    La suppression d’un ´l´ment x dans une liste consiste a ´liminer la premi`re cellule — si elle
                          ee                                `e                    e
existe — qui contient cet ´l´ment x (voir figure 1.4). Cette ´limination s’effectue en modifiant la
                           ee                                 e
valeur du champ suivant du pr´d´cesseur : le successeur du pr´d´cesseur de la cellule de x devient
                               e e                              e e
le successeur de la cellule de x. Un traitement particulier doit ˆtre fait si l’´l´ment a supprimer
                                                                  e             ee      `
est le premier ´l´ment de la liste, car sa cellule n’a pas de pr´d´cesseur. Nous commen¸ons par
               ee                                                e e                        c

     a                                                 a

                                x                                               x

                          (i)                                            (ii)


Fig. 1.4 – Suppression d’un ´l´ment x dans une liste ; (i) avant suppression, (ii) apr`s suppres-
                            ee                                                        e
sion.

une ´criture it´rative.
    e          e
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly
Poly

Más contenido relacionado

Destacado

Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...
Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...
Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...joseluisserrano
 
Biocombustibles 2011
Biocombustibles 2011Biocombustibles 2011
Biocombustibles 2011Daniel Moreno
 
El camino hacia el desarrollo en cbba
El camino hacia el desarrollo en cbbaEl camino hacia el desarrollo en cbba
El camino hacia el desarrollo en cbbaGobernabilidad
 
Contribuerquandonnestpastechnique
ContribuerquandonnestpastechniqueContribuerquandonnestpastechnique
Contribuerquandonnestpastechniqueclarista
 
Azizi_Approche dynamique & Socioanthropologie de la ville africaine
Azizi_Approche dynamique & Socioanthropologie de la ville africaineAzizi_Approche dynamique & Socioanthropologie de la ville africaine
Azizi_Approche dynamique & Socioanthropologie de la ville africaineSouad Azizi
 
Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...
Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...
Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...Universidad Autónoma de Barcelona
 
Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...
Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...
Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...Ann Davidson
 
Nouveauté De Skyline
Nouveauté De SkylineNouveauté De Skyline
Nouveauté De Skylinelecuyer55
 
Double Arts Cap 20
Double Arts Cap 20Double Arts Cap 20
Double Arts Cap 20Kimekiu
 
Chauveau Apero
Chauveau AperoChauveau Apero
Chauveau Aperodark73
 
Note Rf Asian Financial Forum 2009 Hong Kong 20 Janvier 2009 Rev 2010 Lkdin
Note Rf Asian Financial Forum 2009   Hong Kong 20 Janvier 2009   Rev 2010 LkdinNote Rf Asian Financial Forum 2009   Hong Kong 20 Janvier 2009   Rev 2010 Lkdin
Note Rf Asian Financial Forum 2009 Hong Kong 20 Janvier 2009 Rev 2010 LkdinRenaud Favier
 

Destacado (19)

Strasburgo
StrasburgoStrasburgo
Strasburgo
 
Ppt blog
Ppt blogPpt blog
Ppt blog
 
Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...
Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...
Herramientas Telemáticas en Aulas Hospitalarias: una experiencia educativa en...
 
Fem sabó
Fem sabóFem sabó
Fem sabó
 
Biocombustibles 2011
Biocombustibles 2011Biocombustibles 2011
Biocombustibles 2011
 
El camino hacia el desarrollo en cbba
El camino hacia el desarrollo en cbbaEl camino hacia el desarrollo en cbba
El camino hacia el desarrollo en cbba
 
Agua
AguaAgua
Agua
 
Contribuerquandonnestpastechnique
ContribuerquandonnestpastechniqueContribuerquandonnestpastechnique
Contribuerquandonnestpastechnique
 
Inventos argentinos
Inventos argentinosInventos argentinos
Inventos argentinos
 
Azizi_Approche dynamique & Socioanthropologie de la ville africaine
Azizi_Approche dynamique & Socioanthropologie de la ville africaineAzizi_Approche dynamique & Socioanthropologie de la ville africaine
Azizi_Approche dynamique & Socioanthropologie de la ville africaine
 
Semaine Ecole Entreprise 2014 : Les actions Ecoles - Entreprises
Semaine Ecole Entreprise 2014 : Les actions Ecoles - EntreprisesSemaine Ecole Entreprise 2014 : Les actions Ecoles - Entreprises
Semaine Ecole Entreprise 2014 : Les actions Ecoles - Entreprises
 
Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...
Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...
Nuevamente sobre Coca-Cola. Notas a la sentencia de la Audiencia Nacional de ...
 
Android BackupManager
Android BackupManagerAndroid BackupManager
Android BackupManager
 
Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...
Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...
Apprendre à exister et apprendre pour exister: une théorie ancrée sur les ado...
 
Nouveauté De Skyline
Nouveauté De SkylineNouveauté De Skyline
Nouveauté De Skyline
 
Double Arts Cap 20
Double Arts Cap 20Double Arts Cap 20
Double Arts Cap 20
 
Chauveau Apero
Chauveau AperoChauveau Apero
Chauveau Apero
 
Oeufs En Dentelle
Oeufs En DentelleOeufs En Dentelle
Oeufs En Dentelle
 
Note Rf Asian Financial Forum 2009 Hong Kong 20 Janvier 2009 Rev 2010 Lkdin
Note Rf Asian Financial Forum 2009   Hong Kong 20 Janvier 2009   Rev 2010 LkdinNote Rf Asian Financial Forum 2009   Hong Kong 20 Janvier 2009   Rev 2010 Lkdin
Note Rf Asian Financial Forum 2009 Hong Kong 20 Janvier 2009 Rev 2010 Lkdin
 

Similar a Poly (20)

Rapport
RapportRapport
Rapport
 
Polycope java enseignant
Polycope java enseignantPolycope java enseignant
Polycope java enseignant
 
cours de Matlab
 cours de Matlab cours de Matlab
cours de Matlab
 
Recherche de citations
Recherche de citationsRecherche de citations
Recherche de citations
 
R´evision d’ontologies fond´ee sur tableaux.doc
R´evision d’ontologies fond´ee sur tableaux.docR´evision d’ontologies fond´ee sur tableaux.doc
R´evision d’ontologies fond´ee sur tableaux.doc
 
. Poly ac.dvi
. Poly ac.dvi. Poly ac.dvi
. Poly ac.dvi
 
LaTeX Document de démonstration
LaTeX Document de démonstrationLaTeX Document de démonstration
LaTeX Document de démonstration
 
Programme_MEA
Programme_MEAProgramme_MEA
Programme_MEA
 
Coursmp
CoursmpCoursmp
Coursmp
 
Analyse s1
Analyse s1Analyse s1
Analyse s1
 
Media file 3403
Media file 3403Media file 3403
Media file 3403
 
Génération automatique de questions à partir de textes en français
Génération automatique de questions à partir de textes en françaisGénération automatique de questions à partir de textes en français
Génération automatique de questions à partir de textes en français
 
Pdf test
Pdf testPdf test
Pdf test
 
Rapport IA
Rapport IARapport IA
Rapport IA
 
Plafonnage n bi2fr07 hdefforweb3
Plafonnage n bi2fr07 hdefforweb3Plafonnage n bi2fr07 hdefforweb3
Plafonnage n bi2fr07 hdefforweb3
 
Lecture de plans et métré
Lecture de plans et métréLecture de plans et métré
Lecture de plans et métré
 
CECR
CECR CECR
CECR
 
Résolution d'équations différentielles linéaires du premier ordre par la méth...
Résolution d'équations différentielles linéaires du premier ordre par la méth...Résolution d'équations différentielles linéaires du premier ordre par la méth...
Résolution d'équations différentielles linéaires du premier ordre par la méth...
 
p1314558_NGUYEN-Thi-Tuong-Vy
p1314558_NGUYEN-Thi-Tuong-Vyp1314558_NGUYEN-Thi-Tuong-Vy
p1314558_NGUYEN-Thi-Tuong-Vy
 
Cecrl
CecrlCecrl
Cecrl
 

Último

Cours Préparation à l’ISO 27001 version 2022.pdf
Cours Préparation à l’ISO 27001 version 2022.pdfCours Préparation à l’ISO 27001 version 2022.pdf
Cours Préparation à l’ISO 27001 version 2022.pdfssuserc72852
 
Computer Parts in French - Les parties de l'ordinateur.pptx
Computer Parts in French - Les parties de l'ordinateur.pptxComputer Parts in French - Les parties de l'ordinateur.pptx
Computer Parts in French - Les parties de l'ordinateur.pptxRayane619450
 
COURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdf
COURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdfCOURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdf
COURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdfabatanebureau
 
Sidonie au Japon . pptx Un film français
Sidonie    au   Japon  .  pptx  Un film françaisSidonie    au   Japon  .  pptx  Un film français
Sidonie au Japon . pptx Un film françaisTxaruka
 
GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...
GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...
GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...Nguyen Thanh Tu Collection
 
Bolero. pptx . Film de A nnne Fontaine
Bolero. pptx . Film   de  A nnne FontaineBolero. pptx . Film   de  A nnne Fontaine
Bolero. pptx . Film de A nnne FontaineTxaruka
 
Boléro. pptx Film français réalisé par une femme.
Boléro.  pptx   Film   français   réalisé  par une  femme.Boléro.  pptx   Film   français   réalisé  par une  femme.
Boléro. pptx Film français réalisé par une femme.Txaruka
 
La nouvelle femme . pptx Film français
La   nouvelle   femme  . pptx  Film françaisLa   nouvelle   femme  . pptx  Film français
La nouvelle femme . pptx Film françaisTxaruka
 
gestion des conflits dans les entreprises
gestion des  conflits dans les entreprisesgestion des  conflits dans les entreprises
gestion des conflits dans les entreprisesMajdaKtiri2
 
Cours ofppt du Trade-Marketing-Présentation.pdf
Cours ofppt du Trade-Marketing-Présentation.pdfCours ofppt du Trade-Marketing-Présentation.pdf
Cours ofppt du Trade-Marketing-Présentation.pdfachrafbrahimi1
 
Apolonia, Apolonia.pptx Film documentaire
Apolonia, Apolonia.pptx         Film documentaireApolonia, Apolonia.pptx         Film documentaire
Apolonia, Apolonia.pptx Film documentaireTxaruka
 
L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...
L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...
L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...Faga1939
 

Último (13)

Cours Préparation à l’ISO 27001 version 2022.pdf
Cours Préparation à l’ISO 27001 version 2022.pdfCours Préparation à l’ISO 27001 version 2022.pdf
Cours Préparation à l’ISO 27001 version 2022.pdf
 
Computer Parts in French - Les parties de l'ordinateur.pptx
Computer Parts in French - Les parties de l'ordinateur.pptxComputer Parts in French - Les parties de l'ordinateur.pptx
Computer Parts in French - Les parties de l'ordinateur.pptx
 
COURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdf
COURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdfCOURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdf
COURS SVT 3 EME ANNEE COLLEGE 2EME SEM.pdf
 
Sidonie au Japon . pptx Un film français
Sidonie    au   Japon  .  pptx  Un film françaisSidonie    au   Japon  .  pptx  Un film français
Sidonie au Japon . pptx Un film français
 
GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...
GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...
GIÁO ÁN DẠY THÊM (KẾ HOẠCH BÀI DẠY BUỔI 2) - TIẾNG ANH 6, 7 GLOBAL SUCCESS (2...
 
Bolero. pptx . Film de A nnne Fontaine
Bolero. pptx . Film   de  A nnne FontaineBolero. pptx . Film   de  A nnne Fontaine
Bolero. pptx . Film de A nnne Fontaine
 
Boléro. pptx Film français réalisé par une femme.
Boléro.  pptx   Film   français   réalisé  par une  femme.Boléro.  pptx   Film   français   réalisé  par une  femme.
Boléro. pptx Film français réalisé par une femme.
 
Evaluación Alumnos de Ecole Victor Hugo
Evaluación Alumnos de Ecole  Victor HugoEvaluación Alumnos de Ecole  Victor Hugo
Evaluación Alumnos de Ecole Victor Hugo
 
La nouvelle femme . pptx Film français
La   nouvelle   femme  . pptx  Film françaisLa   nouvelle   femme  . pptx  Film français
La nouvelle femme . pptx Film français
 
gestion des conflits dans les entreprises
gestion des  conflits dans les entreprisesgestion des  conflits dans les entreprises
gestion des conflits dans les entreprises
 
Cours ofppt du Trade-Marketing-Présentation.pdf
Cours ofppt du Trade-Marketing-Présentation.pdfCours ofppt du Trade-Marketing-Présentation.pdf
Cours ofppt du Trade-Marketing-Présentation.pdf
 
Apolonia, Apolonia.pptx Film documentaire
Apolonia, Apolonia.pptx         Film documentaireApolonia, Apolonia.pptx         Film documentaire
Apolonia, Apolonia.pptx Film documentaire
 
L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...
L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...
L'ÉVOLUTION DE L'ÉDUCATION AU BRÉSIL À TRAVERS L'HISTOIRE ET LES EXIGENCES DE...
 

Poly

  • 1. Programmation et Algorithmique ´ Ecole Polytechnique ´ Jean Berstel et Jean-Eric Pin
  • 2.
  • 3. Avant-propos Ce polycopi´ est utilis´ pour le cours INF 421 intitul´ Les bases de la programmation et de e e e l’algorithmique. Ce cours fait suite au cours INF 311 Introduction a l’informatique et pr´c`de le ` e e cours INF 431 intitul´ Fondements de l’informatique. e Ce polycopi´ reprend et d´veloppe les chapitres 10 et 11 du polycopi´ de Robert Cori, e e e Jean-Jacques L´vy et Fran¸ois Morain Les bases de la programmation et de l’algorithmique. e c Il fait ´galement suite au polycopi´ de Fran¸ois Morain Les bases de l’informatique et de la e e c programmation. Pour qu’il n’y ait pas confusion avec ce dernier polycopi´, nous avons intitul´ e e le nˆtre plus simplement Programmation et algorithmique. o Comme le lecteur pourra le constater, nous avons suivi pour l’essentiel le canevas des cha- pitres 10 et 11 du polycopi´ de Robert Cori, Jean-Jacques L´vy et Fran¸ois Morain, en incluant e e c des applications et des d´veloppements sur certaines variantes. Nous avons aussi insist´, au e e d´but, sur le concept de r´f´rence, notion qui se retrouve d’ailleurs, sous le terme de pointeur, e ee dans d’autres langages de programmation. Le th`me principal du cours est, du cˆt´ de la programmation, la conception et la mise e oe en œuvre de nouveaux types. Le langage Java le permet de deux fa¸ons, par la cr´ation de c e tableaux, et par la d´finition de classes. Quant a l’algorithmique, c’est la description et l’emploi e ` de structures de donn´es dynamiques qui sont au centre de ce cours. Nous traitons en d´tail e e les listes et les arbres. Leur usage dans la repr´sentation de s´quences et d’ensembles ordonn´s e e e est particuli`rement d´velopp´. Les applications concernent la gestion des partitions (« union- e e e find » en anglais), la compression de textes, les t´trarbres (« quadtrees ») et des probl`mes e e g´om´triques qui ne sont pas tous d´crits dans cette premi`re version du polycopi´. Les structures e e e e e plus ´labor´es, comme les graphes, seront ´tudi´es dans le cours 431. e e e e Nous tenons a remercier en tout premier lieu Robert Cori, Jean-Jacques L´vy et Fran¸ois ` e c Morain qui nous ont autoris´ a reprendre a notre compte certains ´l´ments de leurs polycopi´s. e` ` ee e e ´ Nous remercions aussi nos coll`gues de l’ Ecole Polytechnique, et plus particuli`rement Philippe e ´ Chassignet, Emmanuel Coquery, Fabrice Le Fessant, Laurent Mauborgne, Eric Schost, Alexandre Sedoglavic et Nicolas Sendrier qui ont largement contribu´ a l’´laboration et a la mise au point e` e ` de ce cours. Enfin nous sommes particuli`rement reconnaissants a Catherine Bensoussan et au e ` ´ service de reprographie de l’Ecole Polytechnique pour leur travail exemplaire. Les auteurs peuvent ˆtre contact´s par courrier ´lectronique aux adresses suivantes : e e e berstel@univ-mlv.fr Jean-Eric.Pin@liafa.jussieu.fr On peut aussi consulter les pages Web des auteurs : http : //www-igm.univ-mlv.fr/~berstel http : //liafa.jussieu.fr/~jep 3
  • 4.
  • 5. Table des mati`res e I Compl´ments de programmation e 9 1 R´f´rences . . . . . . . . . . . . . ee . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.1 Types et r´f´rences . . . . ee . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.2 R´f´rences d’objets . . . . ee . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3 Constructeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2 M´thodes et variables statiques . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.1 Variables statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.2 M´thodes statiques . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 3 M´thodes et variables final . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4 La classe String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 II Structures s´quentielles e 25 1 Listes chaˆ ees . . . . . . . . . . . . . . . . . ın´ . . . . . . . . . . . . . . . . . . . . . 26 1.1 D´finitions . . . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . 26 1.2 Fonctions simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 1.3 Op´rations . . . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . 30 Copie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Recherche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Suppression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Concat´nation . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . 33 Inversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 1.4 Une application : les polynˆmes . . . o . . . . . . . . . . . . . . . . . . . . . 36 2 Listes circulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 2.1 D´finitions . . . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . 41 2.2 Op´rations . . . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . 43 Parcours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 2.3 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Permutations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3 Variations sur les listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 4 Hachage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 4.1 Adressage direct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.2 Tables de hachage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.3 R´solution des collisions par chaˆ e ınage . . . . . . . . . . . . . . . . . . . . . 49 4.4 Adressage ouvert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 4.5 Choix des fonctions de hachage . . . . . . . . . . . . . . . . . . . . . . . . . 52 5
  • 6. 6 ` TABLE DES MATIERES III Piles et files 55 1 Piles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 1.1 Implantation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 2 Les exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 2.1 Syntaxe des exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 2.2 Lev´e d’exceptions . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . 62 2.3 Capture des exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 3 Une application : l’´valuation d’expressions e arithm´tiques . e . . . . . . . . . . . . . 64 4 Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 4.1 Implantation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Implantation par tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Implantation par listes chaˆ ees . . ın´ . . . . . . . . . . . . . . . . . . . . . . 69 Choix de l’implantation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 IV Arbres 73 1 D´finitions . . . . . . . . . . . . . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 73 1.1 Graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 1.2 Arbres libres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 1.3 Arbres enracin´s . . . . . . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 74 1.4 Arbres ordonn´s . . . . . . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 75 2 Union-Find, ou gestion des partitions . . . . . . . . . . . . . . . . . . . . . . . . . 75 2.1 Une solution du probl`me . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 75 2.2 Applications de l’algorithme Union-Find . . . . . . . . . . . . . . . . . . . 79 3 Arbres binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 3.1 Compter les arbres binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 3.2 Arbres binaires et mots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Mots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Ordres sur les mots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Codage des arbres binaires . . . . . . . . . . . . . . . . . . . . . . . . . . 81 3.3 Parcours d’arbre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 3.4 Une borne inf´rieure pour les tris par comparaisons e . . . . . . . . . . . . . 83 4 Files de priorit´ . . . . . . . . . . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 84 4.1 Tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 4.2 Implantation d’un tas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 4.3 Arbres de s´lection . . . . . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 89 5 Codage de Huffman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 5.1 Compression des donn´es . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 90 5.2 Algorithme de Huffman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 Codes pr´fixes et arbres . . . . . . . . . . . . . . . e . . . . . . . . . . . . . 91 Construction de l’arbre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Choix de la repr´sentation des donn´es . . . . . . . e e . . . . . . . . . . . . . 94 Implantation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 5.3 Algorithme de Huffman adaptatif . . . . . . . . . . . . . . . . . . . . . . . 97 V Arbres binaires 101 1 Implantation des arbres binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 1.1 Implantation des arbres ordonn´s par arbres binaires e . . . . . . . . . . . . 104 2 Arbres binaires de recherche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 2.1 Recherche d’une cl´ . . . . . . . . . . . . . . . . . . . e . . . . . . . . . . . . 106 2.2 Insertion d’une cl´ . . . . . . . . . . . . . . . . . . . . e . . . . . . . . . . . . 107
  • 7. ` TABLE DES MATIERES 7 2.3 Suppression d’une cl´ . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . 108 2.4 Hauteur moyenne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 3 Arbres ´quilibr´s . . . . . . . . . . . . . . . . . . . e e . . . . . . . . . . . . . . . . . 112 3.1 Arbres AVL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Rotations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Implantation des rotations . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Insertion et suppression dans un arbre AVL . . . . . . . . . . . . . . . . . 115 Implantation : la classe Avl . . . . . . . . . . . . . . . . . . . . . . . . . . 116 3.2 B-arbres et arbres a-b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Arbres a-b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 Insertion dans un arbre a-b . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Suppression dans un arbre a-b . . . . . . . . . . . . . . . . . . . . . . . . . 120 VI Applications 123 1 Recherche dans un nuage de points . . . . . . . . . . . . . . . . . . . . . . . . . . 123 1.1 Construction de l’arbre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 1.2 Recherche de points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 2 T´trarbres . . . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . 126 3 Le probl`me des N corps . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . 128 3.1 Donn´es . . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . . 129 3.2 Vecteurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 3.3 Corps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 3.4 Arbre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 3.5 Calcul des forces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 3.6 Univers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Bibliographie 136 Index 137
  • 8.
  • 9. Chapitre I Compl´ments de programmation e Ce premier chapitre nous permettra de pr´ciser certains points cruciaux de la programmation e en Java. Une premi`re section est consacr´e a l’´tude d´taill´e des r´f´rences, ou adresses. La e e ` e e e ee seconde section fait le point sur les m´thodes et les variables statiques. Nous terminons par e quelques rappels sur les m´thodes et les variables d´clar´s final. e e e 1 R´f´rences ee L’utilisation des adresses se retrouve dans divers langages de programmation (Pascal, C, C++, Java, etc.) et peut paraˆ ıtre un peu d´routante au d´but. Elle devient limpide d`s que e e e l’on en a assimil´ les principes de base et c’est la raison pour laquelle nous y consacrons cette e section. 1.1 Types et r´f´rences ee En Java, les donn´es d’un programme se r´partissent en deux cat´gories selon leur type : e e e les types primitifs et les autres. Les types primitifs comprennent les types d’entiers (byte, short, int, long), les types des r´els (float, double), le type des caract`res (char) et le type des bool´ens e e e (boolean). Les autres types sont les types de tableaux ou d’objets. Par exemple, String est un type d’objets, et int[] est le type d’un tableau d’entiers. La construction de tableaux et la d´finition e de nouvelles classes sont les deux moyens de cr´er de nouveaux types a partir de types donn´s. e ` e Ainsi, une d´finition comme e class Personne { String nom; int age; } d´finit un nouveau type d’objets. Ces deux m´canismes s’emboˆ e e ıtent. Ainsi, class Annuaire { Personne[] liste; } d´finit un type d’objets ayant pour membres un tableau d’objets de type Personne. e La manipulation des donn´es dans un programme Java d´pend de leur type. La r´f´rence e e ee d’une donn´e est l’adresse m´moire o` est log´e la donn´e. La nature pr´cise de l’adresse (entier, e e u e e e mani`re de num´roter, etc) nous int´resse peu. Une r´f´rence est de plus typ´e par le type de la e e e ee e donn´e. e 9
  • 10. 10 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION R`gle. Les donn´es de type primitif sont manipul´es par valeur, les donn´es des autres types e e e e sont manipul´es par r´f´rence. e ee Ainsi, le contenu d’une variable de type int est un entier, le contenu d’une variable de type char est un caract`re, et plus g´n´ralement le contenu d’une variable de type primitif est une e e e valeur de ce type. En revanche, le contenu d’une variable de type non primitif est l’adresse d’une donn´e de ce type. La manipulation de r´f´rences est bien plus limit´e que la manipulation de e ee e types de base : on peut seulement les comparer (par == et !=) et les affecter. L’affectation est une affectation de r´f´rences, et il n’y a donc pas de copie des donn´es r´f´renc´es ! On peut ee e ee e illustrer ce ph´nom`ne par un exemple concret. Si un ami vous annonce son d´m´nagement et e e e e vous donne ses nouvelles coordonn´es, une simple modification dans votre carnet d’adresses vous e permettra de continuer a lui ´crire ou a lui t´l´phoner. Bien entendu, cette modification n’a pas ` e ` ee eu pour effet le d´m´nagement ou le changement de la ligne t´l´phonique de votre ami. C’est e e ee la mˆme chose en Java. Lorsqu’on modifie une r´f´rence, cela n’entraˆ pas le d´placement e ee ıne e physique des donn´es, qu’il faudra donc r´aliser ind´pendamment si on le souhaite. e e e Voici un premier exemple. public static void main(String[] args) { byte[] t = {5, 2, 6}; System.out.println("Tableau " + t) ; } Le r´sultat est e > Tableau [B@f12c4e La deuxi`me chaˆ s’interpr`te comme suit : les deux premiers caract`res repr´sentent le type e ıne e e e d’un tableau d’octets (le crochet ouvrant [ signifie « tableau » et B signifie « octet’)’, le symbole ’@’ signifie « adresse », la fin est l’adresse en hexad´cimal. e Remarque. (Cette remarque peut ˆtre ignor´e en premi`re lecture) Lors d’une impression, la m´thode e e e e println cherche une repr´sentation des donn´es sous la forme d’une chaˆ de caract`res. Celle-ci est fournie e e ıne e par la m´thode toString qui est d´finie pour tout objet. Par d´faut, cette m´thode retourne une chaˆ de e e e e ıne caract`res form´e du nom de la classe, de ’@’ et de l’´criture hexad´cimale du code de hachage de l’objet. e e e e Par d´faut, le code de hachage d’un objet est obtenu en hachant l’adresse de l’objet. Dans notre exemple, e f12c4e est l’´criture hexad´cimale du code de hachage de l’adresse du tableau t. Fr´quemment, une classe e e e red´finit la m´thode toString. Par exemple, la classe String d´finit cette m´thode pour qu’elle retourne la e e e e chaˆ de caract`res contenue dans la donn´e. Ainsi, la chaˆ ”Tableau ” est effectivement affich´e telle ıne e e ıne e quelle. Une figure bien choisie aide beaucoup a la compr´hension du comportement des r´f´rences. ` e ee Pour ce faire, la valeur associ´e a une variable n est dessin´e dans une boˆ ´tiquet´e par n. e ` e ıte e e Dans la figure 1.1, on repr´sente une variable enti`re n dont la valeur est 2. Quand la valeur e e d’une variable est une r´f´rence, c’est-`-dire l’adresse d’une donn´e, la valeur num´rique de cette ee a e e adresse est remplac´e par une fl`che dirig´e vers l’emplacement de la donn´e. e e e e n 2 Fig. 1.1 – Une variable n contenant la valeur 2. Dans la figure 1.2, on repr´sente une variable de tableau d’octets t. La valeur de cette variable e est le d´but de la zone m´moire r´serv´e au tableau d’octets. e e e e
  • 11. ´ ´ 1. REFERENCES 11 t @f12c4e @f12c4e 5 2 6 t 5 2 6 (a) (b) Fig. 1.2 – Une variable t contenant l’adresse d’un tableau de trois octets : (a) situation effective, (b) description symbolique. Quand une variable vaut null, cette valeur est indiqu´e par une petite croix, comme dans la e figure 1.3. t Fig. 1.3 – Une variable t contenant la valeur null. Comme nous l’avons dit, les op´rations sur les adresses sont restreintes. Voici un exemple e d’affectation. public static void main(String[] args) { byte[] t = {5, 2, 6}; byte[] s; s = t; System.out.println("Tableau " + t + " " + s) ; } Le r´sultat est e > Tableau [B@f12c4e [B@f12c4e Avant l’affectation s = t, la valeur de s est ind´finie. Apr`s l’affectation, les variables d´signent e e e le mˆme emplacement dans la m´moire (voir figure 1.4). e e t 5 2 6 t 5 2 6 s   s (a) (b) Fig. 1.4 – (a) avant affectation ; (b) apr`s affectation. e En effet, l’instruction d’affectation s = t copie le contenu de t dans s comme toute affectation, et le contenu est l’adresse du tableau. Continuons notre exploration. En toute logique, puisque apr`s l’affectation s = t, les variables e s et t d´signent le mˆme emplacement m´moire, toute modification peut ˆtre faite indistinctement e e e e via s ou t. En particulier, une modification via s se rep`re aussi via t. Le programme e public static void main(String[] args)
  • 12. 12 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION { byte[] t = {5, 2, 6}; byte[] s = t; s[1] = 8; System.out.println(t[1]) ; } affiche en effet le nombre 8. A contrario, si l’on recopie les valeurs contenues dans le tableau t dans un autre tableau, les donn´es sont s´par´es. e e e public static void main(String[] args) { byte[] t = {5, 2, 6}; byte[] s = new byte[3]; for (int i = 0; i < t.length; i++) s[i] = t[i]; System.out.println(s + " " + t) ; System.out.println(s == t) ; } donne > [B@f12c4e [B@93dee9 > false En effet, avant la boucle for, le tableau s ne contient que des valeurs nulles (figure 1.5). t 5 2 6 t 5 2 6 s 0 0 0 s 5 2 6 (a) (b) Fig. 1.5 – (a) avant copie ; (b) apr`s copie. e 1.2 R´f´rences d’objets ee Ce qui a ´t´ illustr´ sur des tableaux s’applique aussi aux objets, d´finis comme instances ee e e de classes. Reprenons la classe des « personnes » d´j` introduite plus haut. ea class Personne { String nom; int age; } On s’en sert comme dans la m´thode suivante. e public static void main(String[] args) { Personne p = new Personne(); p.nom = "Dominique"; p.age = 22; System.out.println(p);
  • 13. ´ ´ 1. REFERENCES 13 System.out.println(p.nom + ", " + p.age + " ans"); } avec le r´sultat e > Personne@cac268 > Dominique, 22 ans La premi`re ligne affich´e est le contenu de p qui est une r´f´rence ; cette r´f´rence est retourn´e e e ee ee e par l’instruction new Personne(). La deuxi`me ligne donne le contenu des champs de l’objet dont e p contient la r´f´rence. L’objet cr´´ par le programme est repr´sent´ dans la figure 1.6, avant et ee ee e e apr`s remplissage. e nom age nom age p 0 p 22 Dominique Fig. 1.6 – Personne cr´´e par new Personne(), et apr`s remplissage des champs. ee e Comme d´j` dit plus haut, null est une valeur de r´f´rence particuli`re. Ce n’est la r´f´rence ea ee e ee d’aucun objet. On peut affecter null a toute variable r´f´rence, mais aucun champ et aucune ` ee m´thode d’objet n’est accessible par une variable qui contient cette valeur sp´ciale. Une telle e e tentative provoque la lev´e d’une exception de la classe NullPointerException. e L’op´rateur new est utilis´ pour la cr´ation d’un nouvel objet. e e e e ` R`gle. A la cr´ation, les champs d’un objet sont initialis´s a une valeur par d´faut. Cette valeur e e ` e est 0 pour les types primitifs num´riques, false pour le type bool´en, et null pour tout champ e e objet. Et en effet, le programme public static void main(String[] args) { Personne p = new Personne(); System.out.println(p + " nom: " + p.nom + ", age: " + p.age); } affiche > Personne@93dee9 nom: null, age: 0 Compliquons un peu. Nous avons dit que les deux op´rations de cr´ations de nouveaux types sont e e les classes et les tableaux. Cr´ons donc un tableau de trois personnes. L` ´galement, le tableau e ae contient, au d´part, des valeurs par d´faut, donc null puisqu’il s’agit d’un tableau d’objets. e e public static void main(String[] args) { Personne[] t = new Personne[3]; Personne p = new Personne(); p.nom = "Dominique"; p.age = 22; t[1] = p; for (int i = 0; i < t.length; i++) System.out.print(t[i] + " "); }
  • 14. 14 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION Le r´sultat est e > null Personne@93dee9 null La situation est d´crite dans la figure 1.7. e t nom age 22 Dominique p Fig. 1.7 – Tableau de trois personnes. La deuxi`me entr´e est affect´e par copie de la valeur de e e e p. 1.3 Constructeurs Une classe Java est un bloc d’un programme. Une classe d´finit un nouveau type non primitif, e et peut contenir – des attributs (aussi appel´s variables), e – des m´thodes, e – des initialisations, – d’autres classes (classes internes ou imbriqu´es). e Parmi les m´thodes, nous connaissons les m´thodes de classe, ou m´thodes statiques (justement e e e celles qualifi´es static) et les m´thodes d’instance. Les constructeurs sont d’autres m´thodes qui e e e permettent de cr´er des objets tout en affectant aux champs des valeurs. Leur syntaxe est un e peu particuli`re. Un constructeur e – a le mˆme nom que la classe, e – est sans type de retour (pas mˆme void !). e Un constructeur est appel´ par new. Un constructeur particulier, appel´ constructeur par d´faut, e e e est fourni a toute classe : c’est le constructeur sans arguments, celui que nous avons utilis´ ` e jusqu’alors. Il initialise tous les champs de l’objet cr´´ a leur valeur par d´faut. ee ` e Plusieurs constructeurs peuvent coexister. Ceci est dˆ a la possibilit´ de surcharger un nom u` e de m´thode : deux m´thodes sont surcharg´es (ou l’une est une surcharge de l’autre), si elles ont e e e le mˆme nom, mais diff`rent par le nombre ou par le type de leurs arguments. e e Reprenons la classe Personne. Le constructeur par d´faut initialise nom a null et age a 0. e ` ` Voici une nouvelle implantation, avec deux autres constructeurs : class Personne { String nom; int age; Personne() {} Personne(String n, int a) { nom = n; age = a; }
  • 15. ´ ´ 1. REFERENCES 15 Personne(String n) { nom = n; } } Le programme public static void main(String[] args) { Personne p = new Personne("Luc", 23); Personne q = new Personne("Anne"); System.out.println(p.nom + ", " + p.age + " ans."); System.out.println(q.nom + ", " + q.age + " ans."); } affiche > Luc, 23 ans. > Anne, 0 ans. Notons que le constructeur par d´faut cesse d’ˆtre fourni implicitement d`s qu’un autre construc- e e e teur est d´fini. Si l’on veut quand mˆme disposer de ce constructeur, il faut le red´finir — comme e e e nous l’avons fait. Voici un autre exemple. Nous manipulons un ensemble de personnes au moyen d’un annuaire, o` on peut ajouter des personnes, en enlever, et demander si une personne y figure. La classe u Annuaire est form´e d’un tableau de Personne et d’un entier n qui donne la taille de l’annuaire. e class Annuaire { final static int nMax = 12; Personne[] liste = new Personne[nMax]; int n = 0; ... } La constante nMax sert a donner une taille maximale. Les m´thodes a d´finir sont ` e ` e class Annuaire { ... boolean ajouter(String nom, int age) {...} boolean enlever(String nom) {...} int index(String nom) {...} boolean estDans(String nom) {...} void afficher() {...} } On peut s’en servir dans un programme comme public static void main(String[] args) { Annuaire a = new Annuaire(); a.ajouter("Luc", 22); a.ajouter("Anne", 21); a.afficher(); System.out.println();
  • 16. 16 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION boolean x = a.estDans("Luc"); // retourne true a.enlever("Luc"); a.afficher(); } et le r´sultat est e > Luc, 22 ans. > Anne, 21 ans. > > Anne, 21 ans. La m´thode index retourne l’entier i tel que liste[i] a pour champ nom l’argument pass´ en e e param`tre, si un tel entier existe, et −1 sinon. Les m´thodes ajouter et enlever retournent un e e bool´en qui indique si l’op´ration a r´ussi. e e e class Annuaire { final static int nMax = 12; Personne[] liste = new Personne[nMax]; int n = 0; boolean ajouter(String nom, int age) { if (estDans(nom) || n == nMax) return false; liste[n++] = new Personne(nom, age); return true; } boolean enlever(String nom) { int i = index(nom); if (i == -1) return false; for (int j = i + 1; j < n; j++) liste[j - 1] = liste[j]; n--; return true; } int index(String nom) { for (int i = 0; i < n; i++) if (liste[i].nom.equals(nom)) return i; return -1; } boolean estDans(String nom) { return (index(nom) != -1); } void afficher() {
  • 17. ´ 2. METHODES ET VARIABLES STATIQUES 17 for (int i = 0; i < n; i++) { Personne p = liste[i]; System.out.println(p.nom + ", " + p.age + " ans."); } } } Ce programme, comme beaucoup d’autres semblables, doit traiter le probl`me de l’adjonction e d’un ´l´ment a un tableau qui est d´j` plein. La politique de l’autruche consiste a ignorer ce ee ` ea ` cas. Plus s´rieusement, on peut consid´rer deux solutions : traiter le probl`me, ou le signaler. e e e Pour signaler le probl`me, on utilise la m´thode ci-dessus : on ne fait pas l’adjonction, et on e e retourne la valeur false. Une version plus sophistiqu´e, bas´e sur les exceptions, sera d´crite plus e e e loin. Pour traiter le probl`me du tableau plein, il n’y a gu`re qu’une solution : augmenter sa e e taille. Ceci se fait en dupliquant le tableau dans un tableau plus grand, comme d´crit ci-dessous e (la m´thode est a inclure dans la classe Annuaire) : e ` void doublerListe() { Personne[] nouvelleListe = new Personne[2*liste.length]; for (int i = 0; i < liste.length; i++) nouvelleListe[i] = liste[i]; liste = nouvelleListe; } Bien voir que l’on recopie le contenu de l’ancien tableau dans le nouveau, puis que l’on copie l’adresse du nouveau tableau dans la variable contenant l’ancienne adresse. Avec cette m´thode, e la m´thode ajouter peut se r´crire de la fa¸on suivante : e e c boolean ajouter(String nom, int age) { if (estDans(nom)) return false; if (n == liste.length) doublerListe(); liste[n++] = new Personne(nom, age); return true; } En fait, il est si souvent n´cessaire de recopier des tableaux qu’il existe une m´thode toute prˆte e e e propos´e par Java (voir la m´thode System.arraycopy()). De plus, Java dispose de classes qui e e g`rent des tableaux dont la taille augmente automatiquement en cas de besoin. e 2 M´thodes et variables statiques e Comme pour les r´f´rences, la distinction entre m´thodes (ou variables) statiques et non ee e statiques ne pr´sente plus de difficult´ si on a assimil´ les principes de bases. e e e 2.1 Variables statiques Une variable d´clar´e static est commune a tous les objets de la classe. Pour cette raison, e e ` on parle de variable de classe et on peut l’utiliser avec la syntaxe NomdeClasse.nomDeVariable. Par exemple, dans Math.Pi, Pi est une variable final static de la classe Math. En revanche, une variable non statique aura une instance par objet. Une variable statique peut aussi ˆtre manipul´e e e
  • 18. 18 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION a travers un objet de la classe, comme toute variable. Ce faisant, on acc`de toujours a la mˆme ` e ` e variable. Comme une variable statique est attach´e a une classe, et non a un objet, on a la r`gle e ` ` e essentielle suivante. R`gle. Toute modification d’une variable statique peut ˆtre faite indistinctement par n’importe e e quel objet de la classe. Cette modification est visible par tous les objets de la classe. Pour illustrer ce ph´nom`ne, consid´rons une classe contenant une variable statique et une e e e variable non statique. class Paire { static int x; int y; } On peut alors utiliser la variable statique x, sous la forme Paire.x, sans d´clarer d’objet, mais e ´crire Paire.y provoquerait une erreur. Par contre, si on d´clare un objet s de type Paire, on a e e acc`s aux champs s.x et s.y. e class Test { static void main() { Paire s = new Paire(); System.out.println("s.x = " + s.x + ", s.y = " + s.y + ", Paire.x = " + Paire.x); } } Le r´sultat est e > s.x = 0, s.y = 0, Paire.x = 0 Modifions l´g`rement la classe Test. e e 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); } } Le r´sultat est e > t.x = 2, t.y = 3 > s.x = 2, s.y = 0 Comme on le voit, l’instruction t.x = 2 a modifi´ la valeur de la variable statique x. De ce fait, la e valeur retourn´e par s.x est ´galement modifi´e. En revanche, l’instruction t.y = 3 n’a eu aucune e e e influence sur la valeur de s.y. Pour clarifier de tels comportements, il est d’ailleurs pr´f´rable de ee remplacer l’instruction t.x = 2 par Paire.x = 2. Mˆme s’il y a plusieurs objets de la classe Paire, il e
  • 19. ´ 2. METHODES ET VARIABLES STATIQUES 19 n’y a qu’une seule instance de la variable statique x. Les expressions Paire.x, s.x et t.x d´signent e la mˆme donn´e a la mˆme adresse. Une derni`re pr´cision : a l’int´rieur de la classe Paire, la e e ` e e e ` e variable statique Paire.x peut s’´crire plus simplement x, car la classe courante est implicite. e Pour bien illustrer ce qui pr´c`de, voici une l´g`re variation du programme pr´c´dent. e e e e e e class Paire { static int[] x; int y; } class StaticTest { public static void main(String[] args) { Paire.x = new int[1]; Paire.x[0] = 7; System.out.println( "Paire.x = " + Paire.x + ", Paire.x[0] = " + Paire.x[0]); Paire s = new Paire(); s.y = 3; System.out.println("s.x = " + s.x + ", s.y = " + s.y); Paire t = new Paire(); t.y = 4; System.out.println("t.x = " + t.x + ", t.y = " + t.y); } } Ce programme affichera > Paire.x = [I@93dee9, Paire.x[0] = 7 > s.x = [I@93dee9, s.y = 3 > t.x = [I@93dee9, t.y = 4 2.2 M´thodes statiques e Une m´thode d´clar´e static peut ˆtre utilis´e sans r´f´rence a un objet particulier. On e e e e e ee ` parle alors de m´thode de classe. Une m´thode statique n’a pas directement acc`s aux variables e e e non statiques. On peut appeler une m´thode statique par NomdeClasse.nomDeMethode(). Par e exemple, dans Math.abs(), abs() est une m´thode statique de la classe Math. e Une m´thode qui n’est pas d´clar´e static est toujours utilis´e en r´f´rence a un objet. e e e e ee ` On parle alors de m´thode d’objet. On peut appeler une m´thode non statique par nomOb- e e jet.nomDeMethode(). Par exemple, la classe System contient une variable de classe de nom out. L’objet System.out appelle une m´thode d’objet de nom println(). e Pour simplifier l’´criture des m´thodes d’objet, on utilise souvent le mot cl´ this, qui d´signe e e e e l’objet courant. Il n’a jamais la valeur null, et sa valeur ne peut ˆtre modifi´e. Utiliser this dans e e une m´thode statique produit une erreur a la compilation. e ` Pour illustrer ces d´finitions, introduisons simultan´ment dans la classe Paire des m´thodes e e e de classe et des m´thodes d’objet. e class Paire { static int x;
  • 20. 20 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION int y; void affiche_x() // m´thode d’objet e { System.out.println("s.x = " + this.x); } void affiche_y() // m´thode d’objet e { System.out.println("s.y = " + this.y); } static void affiche2_x() // m´thode de classe e { System.out.println("s.x = " + x); } static void affiche3_y(Paire s) { System.out.println("s.y = " + s.y); } } On remarquera la syntaxe utilisant this dans affiche x et dans affiche y et l’utilisation de la variable statique x dans affiche2 x. On notera ´galement la diff´rence entre la m´thode sans e e e param`tre affiche y et la m´thode affiche3 y qui prend en param`tre un objet s de type Paire. e e e Attention en effet au pi`ge suivant : e // Attention, cette m´thode est incorrecte ... e static void affiche2_y() { System.out.println("s.y = " + y); } // ... car y n’est pas "static" ! Maintenant, le programme 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 } produit le r´sultat suivant : e
  • 21. ´ 3. METHODES ET VARIABLES FINAL 21 > s.x = 2 > s.y = 0 > s.x = 2 > s.x = 2 > s.y = 0 3 M´thodes et variables final e La d´claration d’une variable final doit toujours ˆtre accompagn´e d’une initialisation. Une e e e m´thode final ne peut ˆtre surcharg´e. e e e Une variable final ne peut ˆtre modifi´e. Attention toutefois ! Si la variable est un tableau, e e donc une r´f´rence, cette r´f´rence ne change plus, mais les valeurs du tableau peuvent ˆtre ee ee e modifi´es ! e class Test { static final int n = 100; static final int[] a = {1, 2, 3}; public static void main(String args[]) { a[0] = 5; // OK n = 9; // Erreur ! Variable finale } } Les m´thodes d’une classe final sont implicitement final. La classe String est une classe final. e 4 La classe String La manipulation des chaˆ ınes de caract`res est simplifi´e en Java par la classe String. Cette e e classe, dont nous venons de dire qu’elle est finale, permet les op´rations usuelles sur les chaˆ e ınes de caract`res. Toutefois, les objets de la classe String sont immutables, c’est-`-dire qu’ils ne peuvent e a ˆtre modifi´s. Une op´ration sur une chaˆ de caract`re se traduit donc, lors d’une modification, e e e ıne e par la cr´ation d’un nouvel objet. Dans la suite de ce polycopi´, on parlera souvent d’op´rations e e e destructrices et non destructrices ; dans ce contexte, les op´rations de la classe String sont non e destructrices. Il existe une variante, destructrice, des chaˆ ınes de caract`res, la classe StringBuffer. e Les m´thodes de la classe String sont nombreuses. Voici quelques-unes des plus fr´quemment e e utilis´es : e int length() char charAt(int index) String toLowerCase() String toUpperCase() Ainsi "abc".charAt(1) retourne le caract`re b, et e "X2001".toLowerCase() retourne la chaˆ x2001. D’autres m´thodes sont utiles pour la comparaison, l’examen, la mo- ıne e dification. En voici quelques exemples :
  • 22. 22 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION boolean equals(String s) int compareTo(String s) boolean startsWith(String prefix) boolean endsWith(String suffix) int indexOf(String facteur) int lastIndexOf(String facteur) L’´galit´ de deux chaˆ e e ınes de caract`res se teste par equals. Le test par == teste l’´galit´ des e e e adresses. La classe String est tr`s optimis´e en Java, et souvent les chaˆ e e ınes compos´es des mˆmes e e caract`res sont en fait rang´es qu’une seule fois en m´moire (ce qui est possible puisqu’elles sont e e e inmodifiables !). De ce fait, l’´galit´ du contenu implique souvent l’´galit´ des adresses et peut e e e e donc ˆtre test´ de cette mani`re. e e e La m´thode compareTo compare la chaˆ avec l’argument, pour l’ordre alphab´tique. Elle e ıne e retourne un entier n´gatif, 0, ou un entier positif selon que la chaˆ appelante est plus petite, e ıne ´gale ou plus grande que la chaˆ pass´e en argument. Ainsi e ıne e "X2001".compareTo("W1001") retourne un nombre positif. Bien entendu, compareTo retourne 0 si et seulement si equals retourne true. La m´thode indexOf (resp. lastIndexOf) retourne le plus petit (resp. plus grand) indice o` e u la chaˆ en argument commence comme facteur de la chaˆ appelante, et -1 si l’argument n’est ıne ıne pas facteur. Ainsi "X2000001".indexOf("00") "X2000001".lastIndexOf("00") donne 2 et 5. Enfin, voici quelques op´rations de construction : e String valueOf(int i) String substring(int debut, int fin) String concat(String s) String replace(char x, char y) Il existe en fait neuf versions de la m´thode valueOf, qui diff´rent par le type de l’argument e e (celle cit´e ci-dessus a pour argument un int). Elles retournent toutes une chaˆ de caract`res e ıne e repr´sentant la valeur pass´e en param`tre. La m´thode concat retourne une nouvelle chaˆ de e e e e ıne caract`res form´e de la chaˆ appelante et de la chaˆ en param`tre. Enfin, notons la possibilit´ e e ıne ıne e e de cr´er un objet de la classe String implicitement, par l’´num´ration de son ´criture. Ainsi, les e e e e chaˆınes comme ”X2000001” sont des objets de la classe String. La m´thode remplace remplace e toutes les occurrences du caract`re x par le caract`re y. Le mot “remplace” n’est pas tr`s bon, e e e puis que c’est une nouvelle chaˆ de caract`res qui est cr´e. ıne e e Parfois, il est utile de disposer de la suite des caract`res d’un String sous forme d’un tableau. e La m´thode toCharArray() retourne un tel tableau ; r´ciproquement, le constructeur String(char[] e e tableau) construit une chaˆ a partir d’un tableau de caract`res. ıne ` e char[] tableau = "X2000001".toCharArray(); tableau[1]++; String s = new String(tableau); La chaˆ retourn´e est bien sˆ r ”X3000001”. ıne e u Retour sur la m´thode toString(). La m´thode toString() fournit une chaˆ de caract`res e e ıne e contenant une description textuelle de l’objet qui l’appelle. Comme nous l’avons dit plus haut, cette m´thode retourne par d´faut une chaˆ de caract`res form´e du nom de la classe, de e e ıne e e ’@’ et de l’´criture hexad´cimale du code de hachage de l’objet. Pour les objets d´finis par des e e e tableaux, le nom est form´ du pr´fixe [ pour les tableaux, et du codage suivant du nom des e e types :
  • 23. 4. LA CLASSE STRING 23 B byte J long C char Lnom de classe ; objet D double S short F float Z boolean I int Consid´rons l’exemple suivant : e class Exemple { public static void main(String[] args) { Exemple e = new Exemple(); Exemple[] t = new Exemple[12]; Exemple[][] u = new Exemple[12][24]; System.out.println(e) ; System.out.println(t) ; System.out.println(u) ; } } Le r´sultat est : e > Exemple@7182c1 > [LExemple;@3f5d07 > [[LExemple;@fabe9 et en effet, la variable u est un tableau dont les ´l´ments sont des tableaux dont les ´l´ments ee ee sont de type Exemple.
  • 24. 24 ´ CHAPITRE I. COMPLEMENTS DE PROGRAMMATION
  • 25. Chapitre II Structures s´quentielles e Les structures de donn´es en algorithmique sont souvent complexes et de taille variable. e Elles sont souvent aussi dynamiques, au sens o` elles ´voluent, en forme et en taille, en cours u e d’ex´cution d’un programme. Les tableaux pr´sentent, dans cette optique, un certain nombre e e de limitations qui en rendent parfois l’usage peu naturel. Tout d’abord, un tableau est de taille fixe, d´termin´ a sa cr´ation. Il faut donc choisir une e e` e taille suffisante d`s le d´but, ce qui peut amener a un gaspillage consid´rable de place. Et mˆme e e ` e e si l’on a vu large, il arrive que la place manque. Il faut alors proc´der a la cr´ation d’un tableau e ` e plus grand et a une recopie, ce qui repr´sente une perte de temps qui peut ˆtre importante. ` e e Un tableau a une structure fixe, lin´aire. Une modification de l’ordre, par exemple par inser- e tion d’un ´l´ment, oblige a d´placer d’autres ´l´ments du tableau, ce qui peut ˆtre tr`s coˆ teux. ee ` e ee e e u Un tableau est donc rigide, et peu ´conomique si l’ensemble des ´l´ments qu’il contient est appel´ e ee e a ´voluer en cours d’ex´cution. `e e Dans ce chapitre et dans le chapitre suivant, nous introduisons quelques structures dyna- miques. Elles sont utilis´es de fa¸on tr`s intensive en programmation. Leur but est de g´rer un e c e e ensemble fini d’´l´ments dont le nombre n’est pas fix´ a priori et peut ´voluer. ee e e Les structures dynamiques doivent r´pondre a un certain nombre de crit`res. Elles doivent e ` e permettre une bonne gestion de la m´moire, par un usage ´conome de celle-ci. Mais elles doivent e e aussi ˆtre simples a utiliser, pour ne pas ´changer cette ´conomie en m´moire contre une difficult´ e ` e e e e d’emploi, ou un temps d’ex´cution disproportionn´. e e La solution pr´sent´e ici, et g´n´ralement utilis´e, repose sur trois principes : e e e e e – Allocation de la m´moire au fur et a mesure des besoins. On dispose alors de toute la place e ` n´cessaire sans en gaspiller. e – D´finition r´cursive des structures. Elle permettent en contrepoint une programmation e e simple par des m´thodes elle-mˆmes r´cursives, calqu´es sur leur structure. e e e e – Enfin, un petit nombre d’op´rateurs d’acc`s et de modification, a partir desquels on e e ` construit des m´thodes plus ´labor´es par composition. e e e Allouer de la m´moire signifie r´server de la m´moire pour l’utilisation du programme. Apr`s e e e e utilisation, on peut ensuite d´sallouer cette m´moire. Dans des langages tels que PASCAL ou C, e e il faut g´rer soigneusement l’allocation et la d´sallocation. En JAVA, c’est un peu plus simple : e e il faut toujours allouer de la m´moire, mais JAVA se charge de d´sallouer la m´moire qui ne sert e e e plus. On notera que la description ci-dessus repose sur des principes qui ne d´pendent pas du lan- e gage de programmation choisi. En Java, et dans d’autres langages de haut niveau, on peut mˆme e sp´cifier une structure dynamique par une description purement abstraite de ses propri´t´s. Ce e ee style de programmation utilisant des types abstraits rel`ve des cours ult´rieurs (cours 431 et e e cours de majeure). Nous ´tudierons dans ce cours deux types de structures dynamiques. Ce chapitre est consacr´ e e 25
  • 26. 26 ´ CHAPITRE II. STRUCTURES SEQUENTIELLES aux structures dites s´quentielles : listes, piles et files d’attente. Le chapitre suivant traite des e arbres et de leur utilisation. D’autres structures dynamiques, en particulier les graphes, sont trait´es dans le cours « Fondements de l’informatique ». e Les structures consid´r´es servent a manipuler des ensembles. Les ´l´ments de ces ensembles ee ` ee peuvent ˆtre de diff´rentes sortes : nombres entiers ou r´els, chaˆ e e e ınes de caract`res, ou des objets e plus complexes comme des processus, des expressions, des matrices. Le nombre d’´l´ments des ee ensembles varie au cours de l’ex´cution du programme, par ajout et suppression d’´l´ments en e ee cours de traitement. Plus pr´cis´ment, les op´rations que l’on s’autorise sur un ensemble E sont e e e les suivantes : – tester si l’ensemble E est vide. – ajouter l’´l´ment x a l’ensemble E. ee ` – v´rifier si l’´l´ment x appartient a l’ensemble E. e ee ` – supprimer l’´l´ment x de l’ensemble E. ee 1 Listes chaˆ ees ın´ Une liste chaˆn´e est compos´e d’une suite finie de couples form´s d’un ´l´ment et de l’adresse ı e e e ee (r´f´rence) vers l’´l´ment suivant. ee ee Il s’agit d’une structure de base de la programmation, fort ancienne. Un usage syst´matique e en est d´j` fait dans le langage Lisp (LISt Processing), con¸u par John MacCarthy en 1960. ea c Une version plus r´cente de ce langage, Scheme, utilise principalement cette structure. Les listes e sont aussi pr´d´finies en Caml. Dans la plupart des langages a objets, comme C++ et Java, on e e ` trouve des classes g´rant les listes. e La recherche d’un ´l´ment dans une liste s’apparente a un classique « jeu de piste » dont le ee ` but est de retrouver un objet cach´ : on commence par avoir des informations sur un « site » o` e u pourrait se trouver cet objet. En ce lieu, on d´couvre des informations, et une indication sur un e autre site (l’adresse d’un autre site) o` l’objet pourrait se trouver, et ainsi de suite. Le point de u d´part du jeu de piste est l’adresse du premier site qu’il faut visiter. Une version contemporaine e de ce jeu consisterait en une suite de pages Web contenant une information et un lien vers la page suivante. Il y a une analogie ´vidente entre lien et r´f´rence. e ee Notons que l’ordre de la suite des ´l´ments d’une liste chaˆ ee n’est pas connu globalement, ee ın´ puisqu’on ne connaˆ que le successeur d’un ´l´ment. C’est ce caract`re local qui permet une ıt ee e grande souplesse d’organisation : il suffit de modifier, en un seul site, la r´f´rence au site suivant ee pour r´organiser la suite des pages Web. e Les op´rations usuelles sur les listes sont les suivantes : e – cr´er une liste vide. e – tester si une liste est vide. – ajouter un ´l´ment en tˆte de liste. ee e – rechercher un ´l´ment dans une liste. ee – supprimer un ´l´ment dans une liste. ee D’autres op´rations sont : retourner une liste, concat´ner deux listes, fusionner deux listes, etc. e e En Java, les « sites » sont des objets qui poss`dent deux champs : un champ pour le contenu, e et un champ qui contient la r´f´rence vers le site suivant. L’acc`s a la liste se fait par la r´f´rence ee e ` ee au premier site. Il est de tradition d’appeler cellule ce que nous avons appel´ site. e 1.1 D´finitions e Les d´clarations sont les suivantes. On suppose ici que les ´l´ments stock´s dans la liste sont e ee e des entiers. Bien entendu, le sch´ma de d´claration serait le mˆme pour une liste de caract`res, e e e e de bool´ens, ou d’objets de type quelconque. e
  • 27. 1. LISTES CHAˆ EES IN ´ 27 class Liste { int contenu; Liste suivant; Liste (int x, Liste a) { contenu = x; suivant = a; } } Une liste est repr´sent´e par la r´f´rence au premier objet de type Liste. La liste vide, sans e e ee ´l´ment, a pour r´f´rence null. La figure 1.1 repr´sente la forme g´n´rale d’une liste. La liste est ee ee e e e compos´e de cellules. Chacune contient, dans son champ contenu, l’un des ´l´ments de la liste. e ee Le champ suivant contient la r´f´rence a la cellule suivante. La croix dans la derni`re cellule ee ` e indique que sa valeur est null, convention pour indiquer qu’il n’y a pas d’´l´ment suivant. Une ee liste est rep´r´e par la r´f´rence a sa premi`re cellule. ee ee ` e su nu su nu su nu nt nt nt e iva e iva e iva nt nt nt co co co ¢¢¡ ¡ ¡ Fig. 1.1 – Forme g´n´rale d’une liste. e e L’instruction new Liste (x, a) construit une nouvelle cellule dont les champs sont x et a et retourne la r´f´rence a cette cellule. Revenons a notre jeu de piste. Supposons que l’adresse du ee ` ` premier site soit a. L’instruction new Liste (x, a) revient a ins´rer, au d´but du jeu, un nouveau ` e e site, dont le contenu est x. Il contient, comme indication du site suivant, l’adresse de l’ancien point de d´part, soit a. Le nouveau point de d´part est le site fraˆ e e ıchement ins´r´. ee Cr´er une liste de trois entiers, par exemple de 2, 7 et 11 se fait par usage r´p´t´ de l’ins- e e ee truction d’insertion : Liste a = new Liste(2, new Liste (7, new Liste (11, null))) La liste de cet exemple est repr´sent´e dans la figure 1.2. e e a 2 7 11 Fig. 1.2 – Une liste de trois ´l´ments 2, 7, 11 repr´sent´es par trois cellules. ee e e Venons-en aux op´rations sur les listes. La m´thode listeVide retourne une liste vide, c’est- e e a-dire null. ` static Liste listeVide () { return null; }
  • 28. 28 ´ CHAPITRE II. STRUCTURES SEQUENTIELLES La fonction qui teste si une liste est vide s’´crit : e static boolean estVide (Liste a) { return a == null; } Il faut bien dire que ces fonctions sont si simples qu’on les remplace souvent par leur d´finition e dans la pratique. Ajouter un ´l´ment en d´but de liste se fait par : ee e static Liste ajouter (int x, Liste a) { return new Liste (x, a); } L’effet de cette op´ration est repr´sent´ dans la figure 1.3. e e e a ¤¢£ £ £ x Fig. 1.3 – Ajout d’un ´l´ment x au d´but d’une liste a. ee e Ainsi, cr´er une liste contenant seulement x se fait de l’une des quatre fa¸ons ´quivalentes : e c e new Liste(2, null) ajouter(x, null) new Liste(2, listeVide()) ajouter(x, listeVide()) Voici un autre exemple : static Liste suite(int n) { Liste a = null; for (int i = n; i >=1; i--) a = ajouter(i, a); return a; } Cette fonction retourne une liste contenant les entiers de 1 a n, dans cet ordre. Noter le parcours ` d´croissant des entiers dans la boucle. e Deux fonctions d’acc`s sont importantes : celle retournant le contenu, et celle retournant la e r´f´rence a la suite de la liste. Ces fonctions ne doivent ˆtre appel´es que sur des listes non vides. ee ` e e static int tete(Liste a) { return a.contenu; } static Liste queue(Liste a) { return a.suivant; }
  • 29. 1. LISTES CHAˆ EES IN ´ 29 L` encore, on utilise souvent dans la pratique l’expression plutˆt que la fonction. Les trois a o fonctions ajouter, tete et queue sont li´es par les ´quations suivantes. e e tete(ajouter(x, a)) = x queue(ajouter(x, a)) = a ajouter(tete(a), queue(a)) = a; (a = null) Elles permettent de simplifier toute expression compos´e de ces trois fonctions en une forme e r´duite. e Les trois fonctions ajouter, tete et queue permettent de r´aliser beaucoup d’op´rations sur e e les listes. Elles ne permettent pas, en revanche, de modifier la valeur d’un champ, que ce soit le contenu ou la r´f´rence a la cellule suivante. C’est pourquoi on appelle ces fonctions, et ee ` les op´rations qu’elles permettent de r´aliser, des op´rations non destructives, en opposition e e e aux op´rations qui modifient la valeur, qui d´truisent donc les valeurs pr´c´dentes, et qui sont e e e e appel´es destructives. L’usage d’op´rations non destructives pour modifier une donn´e am`ne a e e e e ` la recopie des parties a modifier. ` 1.2 Fonctions simples Voici quelques exemples de fonctions simples et utiles. Elles sont bas´es sur le parcours des e ´l´ments d’une liste. La longueur d’une liste est le nombre d’´l´ments qui la composent. En voici ee ee une r´alisation : e static int longueur(Liste a) { if (estVide(a)) return 0; return 1 + longueur(queue(a)); } On peut l’´crire de mani`re plus condens´e, en utilisant une expression conditionnelle : e e e static int longueur(Liste a) { return (estVide(a)) ? 0 : 1 + longueur(queue(a)); } On peut aussi l’´crire de mani`re it´rative, et par acc`s direct aux champs : e e e e static int longueurI(Liste a) { int n = 0; while (a != null) { n++; a = a.suivant; } return n; } Autre exemple similaire, l’affichage d’une liste. On choisit ici d’afficher les ´l´ments sur une ee ligne, s´par´s par un blanc. e e static void afficher(Liste a) { if (estVide(a)) System.out.println();
  • 30. 30 ´ CHAPITRE II. STRUCTURES SEQUENTIELLES else { System.out.print(a.contenu + " "); afficher(a.suivant); } } Notons que si les deux derni`res instructions de la m´thode pr´c´dente sont interverties, la liste e e e e est affich´e dans l’ordre inverse ! Bien sˆ r, on peut ´crire notre fonction de fa¸on it´rative : e u e c e static void afficherI(Liste a) { while (a != null) { System.out.print(a.contenu + " "); a = a.suivant; } System.out.println(); } 1.3 Op´rations e Copie La copie d’une liste est facile a r´aliser. En voici une version r´cursive. ` e e static Liste copier(Liste a) { if (a == null) return a; return ajouter(tete(a), copier(queue(a)); } Recherche La recherche d’un ´l´ment dans une liste peut aussi se faire it´rativement et r´cursivement. ee e e C’est encore un algorithme bas´ sur un parcours, mais le parcours est interrompu d`s que e e l’´l´ment cherch´ est trouv´. Voici l’´criture it´rative : ee e e e e static boolean estDansI(int x, Liste a) // it´ratif e { while (a != null) { if (a.contenu == x) return true; a = a.suivant; } return false; } La boucle while peut ˆtre transform´e de mani`re m´canique en une boucle for. Dans notre cas, e e e e on obtient l’´criture suivante : e static boolean estDansI(int x, Liste a) // it´ratif e { for(; a!= null; a = a.suivant)
  • 31. 1. LISTES CHAˆ EES IN ´ 31 if (a.contenu == x) return true; return false; } Voici enfin une premi`re version r´cursive. Elle distingue trois cas : une liste vide, o` la recherche e e u ´choue, une liste dont la tˆte est l’´l´ment cherch´, o` la recherche r´ussit, et le cas restant, trait´ e e ee e u e e par r´cursion. e static boolean estDans(int x, Liste a) // r´cursif e { if (a == null) return false; if (a.contenu == x) return true; return estDans(x, a.suivant); } Voici une deuxi`me version, utilisant a la fois les fonctions d’acc`s et une expression bool´enne : e ` e e static boolean estDans(int x, Liste a) // r´cursif e { return !estVide(a) && (tete(a) == x || estDans(x, queue(a))); } En Java, l’´valuation d’expressions bool´ennes se fait de gauche a droite et est toujours pares- e e ` seuse. Ceci signifie que lors de l’´valuation d’une expression bool´enne du type b1 || b2, o` b1 e e u et b2 sont des expressions bool´ennes, Java ´value d’abord b1. Si le r´sultat de cette ´valuation e e e e est true, il en d´duit que la valeur de b1 || b2 est true, sans mˆme ´valuer b2. Par contre, si le e e e r´sultat est false, il poursuit en ´valuant b2. Dans le cas d’une expression du type b1 && b2, le e e mˆme principe paresseux s’applique : si b1 est ´valu´ a false, Java en conclut que b1 && b2 vaut e e e` false sans ´valuer b2. e Dans notre cas, le deuxi`me facteur de la conjonction n’est donc pas ´valu´ si la liste est e e e vide. On voit donc l` un int´rˆt subtil de l’´valuation paresseuse, en sus du gain de temps. Si a ee e l’´valuation n’´tait pas paresseuse, comme c’´tait le cas en PASCAL, un des ancˆtres de JAVA, e e e e l’´valuation de tete(a) provoquerait une erreur... e Suppression La suppression d’un ´l´ment x dans une liste consiste a ´liminer la premi`re cellule — si elle ee `e e existe — qui contient cet ´l´ment x (voir figure 1.4). Cette ´limination s’effectue en modifiant la ee e valeur du champ suivant du pr´d´cesseur : le successeur du pr´d´cesseur de la cellule de x devient e e e e le successeur de la cellule de x. Un traitement particulier doit ˆtre fait si l’´l´ment a supprimer e ee ` est le premier ´l´ment de la liste, car sa cellule n’a pas de pr´d´cesseur. Nous commen¸ons par ee e e c a a x x (i) (ii) Fig. 1.4 – Suppression d’un ´l´ment x dans une liste ; (i) avant suppression, (ii) apr`s suppres- ee e sion. une ´criture it´rative. e e