listes chainée en JAVA

3 987 vues

Publié le

0 commentaire
2 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
3 987
Sur SlideShare
0
Issues des intégrations
0
Intégrations
3
Actions
Partages
0
Téléchargements
70
Commentaires
0
J’aime
2
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

listes chainée en JAVA

  1. 1. Chapitre 14Listes chaˆn´ es ı e14.1 La notion de liste Une liste est une structure de donn´ es qui permet de stocker une s´ quence d’objets d’un mˆ me e e etype. En cela, les listes ressemblent aux tableaux. La s´ quence d’entiers 3, 7, 2, 4 peut etre repr´ sent´ e e ˆ e ea la fois sous forme de tableau ou de liste. La notation [3, 7, 2, 4] repr´ sentera la liste qui contient` ecette s´ quence. e Il y a cependant des diff´ rences fondamentales entre listes et tableaux : e – Dans un tableau on a acc` s imm´ diat a n’importe quel el´ ment par son indice (acc` s dit al´ atoire), e e ` ´e e e tandis que dans une liste chaˆn´ e on a acc` s aux el´ ments un apr` s l’autre, a partir du premier ı e e ´e e ` el´ ment (acc` s dit s´ quentiel). ´e e e – Un tableau a une taille fixe, tandis qu’une liste peut augmenter en taille ind´ finiment (on peut e toujours rajouter un el´ ment a une liste). ´e `D´ finition (r´ cursive) : e e En consid´ rant que la liste la plus simple est la liste vide (not´ e [ ]), qui ne contient aucun el´ ment, e e ´eon peut donner une d´ finition r´ cursive aux listes chaˆn´ es d’´ l´ ments de type T : e e ı e ee – la liste vide [ ] est une liste ; – si e est un el´ ment de type T et l est une liste d’´ l´ ments de type T, alors le couple (e, l) est ´e ee aussi une liste, qui a comme premier el´ ment e et dont le reste des el´ ments (` partir du second) ´e ´e a forment la liste l. Cette d´ finition est r´ cursive, car une liste est d´ finie en fonction d’une autre liste. Une telle e e ed´ finition r´ cursive est correcte, car une liste est d´ finie en fonction d’une liste plus courte, qui contient e e eun el´ ment de moins. Cette d´ finition permet de construire n’importe quelle liste en partant de la liste ´e evide.Conclusion : la liste chaˆn´ e est une structure de donn´ es r´ cursive. ı e e e La validit´ de cette d´ finition r´ cursive peut etre discut´ e d’un point de vue diff´ rent. Elle peut e e e ˆ e eetre exprim´ e sous la forme suivante : quelque soit la liste l consid´ r´ e,ˆ e ee – soit l est la liste vide [ ], – soit l peut etre d´ compos´ e en un premier el´ ment e et un reste r de la liste, l=(e, r). ˆ e e ´e Cette d´ finition donne une d´ composition r´ cursive des listes. La condition g´ n´ rale d’arrˆ t de e e e e e er´ cursivit´ est pour la liste vide. Cette d´ composition est valide, car la liste est r´ duite a chaque pas e e e e `a une liste plus courte d’une unit´ . Cela garantit que la d´ composition m` ne toujours a une liste de` e e e `longueur 0, la liste vide (condition d’arrˆ t). e 1
  2. 2. 2 ˆ ´ CHAPITRE 14. LISTES CHAINEES 14.2 Repr´ sentation des listes chaˆn´ es en Java e ı e Il y a plusieurs facons de repr´ senter les listes chaˆn´ es en Java. L’id´ e de base est d’utiliser un ¸ e ı e e enchaˆnement de cellules : ı – chaque cellule contient un el´ ment de la liste ; ´e – chaque cellule contient une r´ f´ rence vers la cellule suivante, sauf la derni` re cellule de la liste ee e (qui contient une r´ f´ rence nulle) ; ee – la liste donne acc` s a la premi` re cellule, le reste de la liste est accessible en passant de cellule e ` e en cellule, suivant leur enchaˆnement. ı La figure 14.1 illustre cette repr´ sentation pour la liste exemple ci-dessus [3, 7, 2, 4]. e liste 3 7 2 4 F IG . 14.1 – Repr´ sentation par enchaˆnement de cellules de la liste [3, 7, 2, 4] e ı En Java, les r´ f´ rences ne sont pas d´ finies explicitement, mais implicitement a travers les objets : ee e ` un objet est repr´ sent´ par une r´ f´ rence vers la zone de m´ moire qui contient ses variables d’instance. e e ee e Comme une liste est d´ finie par une r´ f´ rence vers une cellule (la premi` re de la liste), la m´ thode e ee e e la plus simple est de repr´ senter une liste par sa premi` re cellule. La classe suivante d´ finit une liste e e e d’entiers. Listing 14.1 – (lien vers le code brut)1 class Liste {2 int element ;3 Liste suivant ;45 L i s t e ( i nt premier , L i s t e r e s t e ){6 element = premier ;7 suivant = reste ;8 }9 } Le constructeur de la classe Liste cr´ e une liste comme une premi` re cellule qui contient le e e premier el´ ment de la liste et une r´ f´ rence vers le reste de la liste. ´e ee Remarque : Cette solution a l’inconv´ nient de ne repr´ senter que des listes avec au moins une cel- e e lule. La liste vide, qui selon la d´ finition est egalement une liste, ne peut pas etre un objet de e ´ ˆ la classe Liste. Il est n´ anmoins possible de repr´ senter la liste vide par une r´ f´ rence nulle. e e ee Cette repr´ sentation imparfaite des listes a l’avantage de la simplicit´ et nous l’utiliserons dans e e le reste de ce cours. 14.3 Op´ rations sur les listes chaˆn´ es e ı e Nous etudierons les op´ rations les plus importantes sur les listes chaˆn´ es, qui seront repr´ sent´ es ´ e ı e e e comme des m´ thodes de la classe Liste. e Remarque : Puisque la classe Liste ne peut pas repr´ senter la liste vide, des op´ rations de base e e comme le test de liste vide ou l’action de vider une liste ne peuvent pas etre des m´ thodes de la ˆ e
  3. 3. ´ ˆ ´ 14.3. OPERATIONS SUR LES LISTES CHAINEES 3 classe Liste. Ces op´ rations doivent etre effectu´ es a l’ext´ rieur de la classe Liste, par le e ˆ e ` e programme qui utilise les listes. Conform´ ment a leur d´ finition, les listes sont des structures r´ cursives. Par cons´ quent, les e ` e e e op´ rations sur les listes s’expriment naturellement par des algorithmes r´ cursifs. En mˆ me temps, e e e les listes sont des structures lin´ aires, parfaitement adapt´ es a un parcours it´ ratif. Nous donnerons e e ` e aussi la variante it´ rative des op´ rations sur listes, a titre comparatif. e e ` La repr´ sentation de la classe Liste ci-dessous montre sous forme de m´ thodes les op´ rations e e e sur listes que nous discuterons. Listing 14.2 – (lien vers le code brut) 1 class Liste { 2 int element ; 3 Liste suivant ; 4 5 public L i s t e ( i nt premier , L i s t e r e s t e ){ 6 element = premier ; 7 suivant = reste ; 8 } 910 public int premier ( ) { . . . }11 public Liste reste ( ) { . . . }12 public v o i d m o d i f i e P r e m i e r ( i n t elem ) { . . . }13 public void m o d i f i e R e s t e ( L i s t e r e s t e ) { . . . }14 public int longueur ( ) { . . . }15 public b o o l e a n c o n t i e n t ( i n t elem ) { . . . }16 public L i s t e i n s e r t i o n D e b u t ( i n t elem ) { . . . }17 public void c o n c a t e n a t i o n ( L i s t e l i s t e ) { . . . }18 public L i s t e s u p p r e s s i o n P r e m i e r ( i n t elem ) { . . . }19 } 14.3.1 Op´ rations sans parcours de liste e Pour ces op´ rations il n’y a pas de variantes it´ ratives et r´ cursives, l’action est r´ alis´ e directe- e e e e e ment sur la tˆ te de la liste. e ´e Obtenir le premier el´ ment et le reste de la liste Ces op´ rations sont r´ alis´ es par les m´ thodes premier (qui retourne le premier el´ ment de la e e e e ´e liste), respectivement reste (qui retourne le reste de la liste). En fait, ces m´ thodes ne sont pas n´ cessaires, au sens strict du terme, puisque dans la classe e e Liste on a acc` s direct aux variables d’instance element et suivant. e Nous verrons plus tard que l’acc` s direct aux variables d’instance est d´ conseill´ dans la program- e e e mation orient´ e-objet. A la place, on pr´ ferre “cacher” les variables d’instance et donner acc` s a leur e e e ` valeurs a travers des m´ thodes. Ceci fera l’objet d’un prochain cours. ` e Aussi, ces m´ thodes correspondent aux el´ ments de la d´ composition r´ cursive d’une liste et sont e ´e e e bien adapt´ es a l’´ criture d’algorithmes r´ cursifs sur les listes. e ` e e Listing 14.3 – (lien vers le code brut)1 public int premier (){
  4. 4. 4 ˆ ´ CHAPITRE 14. LISTES CHAINEES2 return element ;3 }45 public Liste r e s t e (){6 return s u i v a n t ;7 } Remarque : Il ne faut pas oublier que premier et reste sont des m´ thodes de la classe Liste, e donc une instruction comme return element signifie return this.element. Une liste est repr´ sent´ e par sa premi` re cellule, donc return this.element retourne l’´ l´ ment e e e ee de cette premi` re cellule. e ´e Modifier le premier el´ ment et le reste de la liste Ces op´ rations sont r´ alis´ es par les m´ thodes modifiePremier (qui modifie le premier el´ ment e e e e ´e de la liste), respectivement modifieReste (qui modifie le reste de la liste). Ces m´ thodes permettent donc de modifier les composants element et suivant de la premi` re e e cellule de la liste. Elles sont compl´ mentaires aux m´ thodes premier et reste, qui permettent de e e consulter ces mˆ mes composants. e Leur pr´ sence dans la classe Liste correspond au mˆ me principe que celui evoqu´ pour premier e e ´ e et reste : remplacer l’acc` s direct aux variables d’instance par des appels de m´ thodes. e e Listing 14.4 – (lien vers le code brut)1 p u b l i c v o i d m o d i f i e P r e m i e r ( i n t elem ) {2 e l e m e n t = elem ;3 }45 public void m o d i f i e R e s t e ( L i s t e r e s t e ){6 suivant = reste ;7 } e ´e Ins´ rer un el´ ment en tˆ te de liste e L’insertion en tˆ te de liste est r´ alis´ e par la m´ thode insertionDebut. C’est une op´ ration e e e e e simple, car elle n´ cessite juste un acc` s a la tˆ te de la liste initiale. On cr´ e une nouvelle cellule, a e e ` e e ` laquelle on enchaˆne l’ancienne liste. ı La m´ thode insertionDebut retourne une nouvelle liste, car la liste initiale est modifi´ e par e e l’insertion (la premi` re cellule de la nouvelle liste est diff´ rente). e e Listing 14.5 – (lien vers le code brut)1 p u b l i c L i s t e i n s e r t i o n D e b u t ( i n t elem ) {2 r e t u r n new L i s t e ( elem , t h i s ) ;3 } 14.3.2 Op´ rations avec parcours de liste - variante it´ rative e e Ces op´ rations n´ cessitent un parcours complet ou partiel de la liste. Dans la variante it´ rative, e e e le parcours est r´ alis´ a l’aide d’une r´ f´ rence qui part de la premi` re cellule de la liste et suit l’en- e e` ee e chaˆnement des cellules. ı
  5. 5. ´ ˆ ´ 14.3. OPERATIONS SUR LES LISTES CHAINEES 5 La figure 14.2 illustre le principe du parcours it´ ratif d’une liste a l’aide d’une r´ f´ rence ref. e ` ee ref ........ ref liste e1 ... ei ... en F IG . 14.2 – Parcours it´ ratif d’une liste a l’aide d’une r´ f´ rence e ` ee Calculer la longueur d’une liste Cette op´ ration, r´ alis´ e par la m´ thode longueur, n´ cessite un parcours complet de la liste e e e e e pour compter le nombre de cellules trouv´ es. e Listing 14.6 – (lien vers le code brut)1 public int longueur (){2 i n t compteur = 0 ;3 Liste ref=this ;4 while ( r e f != n u l l ){5 c o m p t e u r ++;6 ref=ref . reste (); / / ou r e f = r e f . s u i v a n t7 }8 return compteur ;9 } Remarque : La r´ f´ rence ref est positionn´ e au d´ but sur la premi` re cellule de la liste et avance ee e e e jusqu’` ce qu’elle devient nulle a la fin de la liste. Chaque fois qu’elle pointe vers une nouvelle a ` cellule, le compteur est incr´ ment´ . Remarquez que l’avancement dans la liste se fait en utili- e e sant la m´ thode reste de la cellule courante, ou sinon l’acc` s direct a la variable d’instance e e ` suivant. ´e ` V´ rifier l’appartenance d’un el´ ment a une liste e Cette op´ ration, r´ alis´ e par la m´ thode contient, n´ cessite un parcours partiel de la liste pour e e e e e chercher l’´ l´ ment en question. Si l’´ l´ ment est retrouv´ , le parcours s’arrˆ te a ce moment-l` , sinon il ee ee e e ` a continue jusqu’` la fin de la liste. a Listing 14.7 – (lien vers le code brut)1 p u b l i c b o o l e a n c o n t i e n t ( i n t elem ) {2 Liste ref=this ;3 while ( r e f != n u l l ){4 i f ( r e f . p r e m i e r ( ) == elem ) / / ou r e f . e l e m e n t==e l e m5 return true ; / / l ’ element a ete retrouve6 else ref=ref . reste (); / / ou r e f = r e f . s u i v a n t7 }8 return f a l s e ; / / l ’ element n ’ a pas e t e r e t r o u v e9 }
  6. 6. 6 ˆ ´ CHAPITRE 14. LISTES CHAINEES Remarque : L’arrˆ t du parcours en cas de succ` s se fait en retournant directement true pendant e e l’ex´ cution de la boucle, ce qui termine a la fois la boucle et la fonction. Remarquez que le test e ` de l’´ l´ ment courant point´ par la r´ f´ rence utilise la m´ thode premier de la cellule courante, ee e ee e ou sinon l’acc` s direct a la variable d’instance element. e ` Concat´ nation de deux listes e Cette op´ ration, r´ alis´ e par la m´ thode concatenation, rajoute a la fin de la liste courante e e e e ` toutes les cellules de la liste pass´ e en param` tre. Elle n´ cessite un parcours complet de la liste cou- e e e rante, afin de trouver sa derni` re cellule. e La liste obtenue par concat´ nation a toujours la mˆ me premi` re cellule que la liste initiale. On e e e peut dire donc que la liste initiale a et´ modifi´ e, en lui rajoutant par concat´ nation une autre liste. ´e e e Listing 14.8 – (lien vers le code brut)1 public void c o n c a t e n a t i o n ( L i s t e l i s t e ){2 Liste ref=this ;3 while ( r e f . r e s t e ( ) != n u l l ){ / / ou r e f . s u i v a n t != n u l l4 ref=ref . reste (); / / ou r e f = r e f . s u i v a n t5 }6 / / re f pointe maintenant sur la d e r n i e r e c e l l u l e de l a l i s t e7 ref . modifieReste ( l i s t e ) ; / / ou r e f . s u i v a n t= l i s t e8 } Remarque : La condition de la boucle while change ici, car on veut s’arrˆ ter sur la derni` re cellule et e e non pas la d´ passer comme dans les m´ thodes pr´ c´ dentes. Remarquez que l’enchaˆnement des e e e e ı deux listes se fait en modifiant la variable d’instance suivant de la derni` re cellule a l’aide e ` de la m´ thode modifieReste, ou sinon par modification directe de celle-ci. e ´e Suppression de la premi` re occurrence d’un el´ ment e Cette op´ ration, r´ alis´ e par la m´ thode suppressionPremier, elimine de la liste la premi` re e e e e ´ e apparition de l’´ l´ ment donn´ en param` tre (s’il existe). La m´ thode retourne une liste, car la liste ee e e e obtenue par suppression peut avoir une autre premi` re cellule que la liste initiale. Ceci arrive quand la e cellule elimin´ e est exactement la premi` re de la liste. ´ e e La suppression d’une cellule de la liste se fait de la mani` re suivante (voir la figure 14.3) : e – si la cellule est la premi` re de la liste, la nouvelle liste sera celle qui commence avec la seconde e cellule. – sinon la cellule a un pr´ d´ cesseur ; pour eliminer la cellule il faut la “court-circuiter”, en mo- e e ´ difiant la variable suivant du pr´ d´ cesseur pour qu’elle pointe vers la mˆ me chose que la e e e variable suivant de la cellule. pred ref pred ref liste liste e e2 ... e1 ... ei e ... nouvelle liste F IG . 14.3 – Suppression d’une cellule de la liste
  7. 7. ´ ˆ ´ 14.3. OPERATIONS SUR LES LISTES CHAINEES 7 Le parcours de la liste a la recherche de l’´ l´ ment donn´ a une particularit´ : si la r´ f´ rence ` ee e e ee s’arrˆ te sur la cellule qui contient l’´ l´ ment, la suppression n’est plus possible, car on n’a plus acc` s e ee e au pr´ d´ cesseur (dans les listes chaˆn´ es on ne peut plus revenir en arri` re). e e ı e e La m´ thode utilis´ e est alors de parcourir la liste avec deux r´ f´ rences : e e ee – une (ref) qui cherche la cellule a eliminer ; `´ – une autre (pred) qui se trouve toujours sur le pr´ d´ cesseur de ref. e e Listing 14.9 – (lien vers le code brut) 1 p u b l i c L i s t e s u p p r e s s i o n P r e m i e r ( i n t elem ) { 2 Liste ref=this ; / / r e f e r e n c e qui cherche elem 3 L i s t e pred= null ; / / predecesseur , i n i t i a l i s e a nu l l 4 w h i l e ( r e f ! = n u l l && r e f . p r e m i e r ( ) ! = elem ) { / / r e c h e r c h e elem 5 pred = r e f ; / / avance pred 6 ref = ref . reste (); / / avance r e f 7 } 8 i f ( r e f != n u l l ){ / / elem t r o u v e dans l a c e l l u l e r e f 9 i f ( p r e d == n u l l ) / / p r e m i e r e c e l l u l e de l a l i s t e10 return r e f . r e s t e ( ) ; / / r e t o u r n e l e r e s t e de l a l i s t e11 else { / / m i l i e u de l a l i s t e12 p r e d . m o d i f i e R e s t e ( r e f . r e s t e ( ) ) ; / / m o d i f i e l e s u i v a n t du p r e d e c e s s e u r13 return t h i s ; / / p r e m i e r e c e l l u l e non m o d i f i e e14 }15 }16 e l s e return t h i s ; / / e l e m e n t non t r o u v e17 } 14.3.3 Op´ rations avec parcours de liste - variante r´ cursive e e Ces op´ rations sont bas´ es sur une d´ composition r´ cursive de la liste en un premier el´ ment et e e e e ´e le reste de la liste (voir la figure 14.4). Le cas le plus simple (condition d’arrˆ t) est la liste avec une e seule cellule. premier reste liste e ... F IG . 14.4 – D´ composition r´ cursive d’une liste e e Calcul r´ cursif de la longueur d’une liste e La formule r´ cursive est : e liste.longueur() = 1 si reste==null 1 + reste.longueur() si reste!=null La fonction r´ cursive longueur s’´ crit alors tr` s facilement, comme suit : e e e Listing 14.10 – (lien vers le code brut)1 public int longueur (){
  8. 8. 8 ˆ ´ CHAPITRE 14. LISTES CHAINEES2 Liste resteListe = reste () ; / / ou r e s t e L i s t e = s u i v a n t ;3 i f ( r e s t e L i s t e == n u l l ) / / condition d ’ arret4 return 1;5 e l s e return 1 + r e s t e L i s t e . longueur ( ) ;6 } e e ` V´ rification r´ cursive de l’appartenance a une liste La formule r´ cursive est : e liste.contient(e) = true si premier==e false si premier!=e et reste==null reste.contient(e) si premier!=e et reste!=null Remarquez que dans ce cas il y a deux conditions d’arrˆ t : quand on trouve l’´ l´ ment recherch´ ou e ee e quand la liste n’a plus de suite (reste est vide). La fonction r´ cursive contient s’´ crit alors comme e e suit : Listing 14.11 – (lien vers le code brut)1 p u b l i c b o o l e a n c o n t i e n t ( i n t elem ) {2 i f ( elem == p r e m i e r ( ) ) r e t u r n t r u e ; / / ou e l e m==e l e m e n t3 Liste resteListe = reste () ; / / ou r e s t e L i s t e = s u i v a n t ;4 i f ( r e s t e L i s t e == n u l l ) / / condition d ’ arret5 return f a l s e ;6 e l s e r e t u r n r e s t e L i s t e . c o n t i e n t ( elem ) ;7 } Concat´ nation r´ cursive de deux listes e e L’action r´ cursive est : e liste.concatenation(l): reste=l si reste==null reste.concatenation(l) si reste!=null Si la liste a une seule cellule (pas de cellule suivante, reste est vide), alors il faut modifier la r´ f´ rence vers la cellule suivante pour enchaˆner la liste param` tre. Sinon, il suffit de concat´ ner le ee ı e e reste avec la liste param` tre. e Listing 14.12 – (lien vers le code brut)1 public void c o n c a t e n a t i o n ( L i s t e l i s t e ){2 Liste resteListe = reste () ; / / ou r e s t e L i s t e = s u i v a n t ;3 i f ( r e s t e L i s t e == n u l l ) / / condition d ’ arret4 modifieReste ( l i s t e ) ; / / ou s u i v a n t= l i s t e5 else resteListe . concatenation ( l i s t e );6 }
  9. 9. ´ ˆ ´ 14.3. OPERATIONS SUR LES LISTES CHAINEES 9 e e ´e Suppression r´ cursive de la premi` re occurrence d’un el´ ment La formule r´ cursive est : e liste.suppressionPremier(e) = reste si premier==e Liste(premier, null) si premier!=e et reste==null Liste(premier, reste.suppressionPremier(e)) si premier!=e et reste != null Si le premier el´ ment de la liste est celui recherch´ , le r´ sultat sera le reste de la liste. Sinon, il ´e e e faut supprimer r´ cursivement l’´ l´ ment recherch´ du reste. Mais le r´ sultat de cette suppression est e ee e e une liste qui provient de reste, donc elle n’a plus le premier el´ ment de la liste initiale. Il faut donc le ´e rajouter en tˆ te de liste. e Listing 14.13 – (lien vers le code brut)1 p u b l i c L i s t e s u p p r e s s i o n P r e m i e r ( i n t elem ) {2 Liste resteListe = reste () ; / / ou r e s t e L i s t e = s u i v a n t ;3 i f ( elem == p r e m i e r ( ) ) / / ou e l e m==e l e m e n t4 return r e s t e L i s t e ;5 e l s e i f ( r e s t e L i s t e == n u l l ) r e t u r n new L i s t e ( p r e m i e r ( ) , n u l l ) ;6 e l s e r e t u r n new L i s t e ( p r e m i e r ( ) , r e s t e L i s t e . s u p p r e s s i o n P r e m i e r ( elem ) ) ;7 } Remarque : L’inconv´ nient de cette m´ thode est qu’on cr´ e des copies de toutes les cellules qui ne e e e contiennent pas l’´ l´ ment recherch´ . Pour eviter cela, la d´ finition doit m´ langer calcul et effets ee e ´ e e de bord, comme suit : liste.suppressionPremier(e) = reste si premier==e liste si premier!=e et reste==null liste apr`s l’action reste=reste.suppressionPremier(e) e si premier!=e et reste!=null Listing 14.14 – (lien vers le code brut) 1 p u b l i c L i s t e s u p p r e s s i o n P r e m i e r ( i n t elem ) { 2 Liste resteListe = reste () ; / / ou r e s t e L i s t e = s u i v a n t ; 3 i f ( elem == p r e m i e r ( ) ) / / ou e l e m==e l e m e n t 4 return r e s t e L i s t e ; 5 e l s e i f ( r e s t e L i s t e == n u l l ) r e t u r n t h i s ; 6 else { 7 m o d i f i e R e s t e ( r e s t e L i s t e . s u p p r e s s i o n P r e m i e r ( elem ) ) ; 8 return t h i s ; 9 }10 }
  10. 10. 10 ˆ ´ CHAPITRE 14. LISTES CHAINEES 14.4 Listes tri´ es e Nous nous int´ ressons maintenant aux listes chaˆn´ es dans lesquelles les el´ ments respectent un e ı e ´e ordre croissant. Dans ce cas, les m´ thodes de recherche, d’insertion et de suppression sont diff´ rentes. e e L’ordre des el´ ments permet d’arrˆ ter plus tˆ t la recherche d’un el´ ment qui n’existe pas dans la liste. ´e e o ´e Aussi, l’insertion ne se fait plus en d´ but de liste, mais a la place qui pr´ serve l’ordre des el´ ments. e ` e ´e Nous utiliserons une classe ListeTriee qui est tr` s similaire a la classe Liste, mais dans la- e ` quelle on s’int´ resse uniquement aux m´ thodes de recherche (contientTriee), d’insertion (insertionTriee) e e et de suppression (suppressionTriee). Les autres m´ thodes sont identiques a celles de la classe e ` Liste. Listing 14.15 – (lien vers le code brut) 1 class ListeTriee { 2 int element ; 3 ListeTriee suivant ; 4 5 public L i s t e T r i e e ( i nt premier , L i s t e T r i e e r e s t e ){ 6 element = premier ; 7 suivant = reste ; 8 } 910 public int premier ( ) { . . . }11 public ListeTriee reste ( ) { . . . }12 public v o i d m o d i f i e P r e m i e r ( i n t elem ) { . . . }13 public void m o d i f i e R e s t e ( L i s t e T r i e e r e s t e ) { . . . }1415 p u b l i c b o o l e a n c o n t i e n t T r i e e ( i n t elem ) { . . . }16 p u b l i c L i s t e T r i e e i n s e r t i o n T r i e e ( i n t elem ) { . . . }17 p u b l i c L i s t e T r i e e s u p p r e s s i o n T r i e e ( i n t elem ) { . . . }18 } 14.4.1 Recherche dans une liste tri´ e e La diff´ rence avec la m´ thode contient de Liste est que dans le parcours de la liste on peut e e s’arrˆ ter d` s que la cellule courante contient un el´ ment plus grand que celui recherch´ . Comme tous e e ´e e les el´ ments suivants vont en ordre croissant, ils seront egalement plus grands que l’´ l´ ment recherch´ . ´e ´ ee e Variante iterative : Listing 14.16 – (lien vers le code brut)1 p u b l i c b o o l e a n c o n t i e n t T r i e e ( i n t elem ) {2 ListeTriee ref=this ;3 w h i l e ( r e f ! = n u l l && r e f . p r e m i e r ( ) <= elem ) {4 i f ( r e f . p r e m i e r ( ) == elem )5 return true ;6 else ref=ref . reste ();7 }8 return f a l s e ;9 }
  11. 11. ´ 14.4. LISTES TRIEES 11 Variante r´ cursive : e Listing 14.17 – (lien vers le code brut)1 p u b l i c b o o l e a n c o n t i e n t T r i e e ( i n t elem ) {2 i f ( elem == p r e m i e r ( ) ) r e t u r n t r u e ;3 i f ( elem < p r e m i e r ( ) ) r e t u r n f a l s e ;4 ListeTriee resteListe = reste () ;5 i f ( r e s t e L i s t e == n u l l )6 return f a l s e ;7 e l s e r e t u r n r e s t e L i s t e . c o n t i e n t T r i e e ( elem ) ;8 } 14.4.2 Insertion dans une liste tri´ e e L’insertion d’un el´ ment doit se faire a la bonne place dans la liste. La bonne place est juste avant ´e ` la premi` re cellule qui contient un el´ ment plus grand que celui a ins´ rer. e ´e ` e Variante iterative : La figure 14.5 montre les deux cas d’insertion : – en d´ but de liste. e Elle est similaire alors a l’op´ ration insertionDebut de la classe Liste ` e – en milieu de liste. La recheche de la position d’insertion se fait alors avec une m´ thode similaire a celle uti- e ` lis´ e pour la m´ thode suppressionPremier de la classe Liste, avec deux r´ f´ rences. e e ee Le pr´ d´ cesseur doit etre modifi´ pour pointer vers la nouvelle cellule, tandis que celle-ci doit e e ˆ e pointer vers la cellule courante (ref). pred ref pred ref liste liste nouvelle liste e1 ... e1 ... ep er ... e e F IG . 14.5 – Insertion dans une liste tri´ e e Dans la figure 14.5, a droite, la r´ f´ rence ref peut ne pas pointer vers une cellule. Ceci arrive quand ` ee l’´ l´ ment a ins´ rer est plus grand que tous les el´ ments de la liste. Dans ce cas, l’insertion se fait a ee ` e ´e ` la fin de la liste, donc au moment de l’arrˆ t de la recherche, ref est nulle et pred est sur la derni` re e e cellule de la liste. Ce cas est identique a celui pr´ sent´ dans la figure 14.5, a la variable suivant de ` e e ` la nouvelle cellule on donne tout simplement la valeur de ref. Listing 14.18 – (lien vers le code brut)1 p u b l i c L i s t e T r i e e i n s e r t i o n T r i e e ( i n t elem ) {2 ListeTriee ref=this ; / / r e f e r e n c e qui cherche elem3 L i s t e T r i e e pred= null ; / / predecesseur , i n i t i a l i s e a nu l l4 w h i l e ( r e f ! = n u l l && r e f . p r e m i e r ( ) < elem ) { / / recherche position5 pred = r e f ; / / avance pred6 ref = ref . reste (); / / avance r e f
  12. 12. 12 ˆ ´ CHAPITRE 14. LISTES CHAINEES 7 } 8 i f ( p r e d == n u l l ) / / i n s e r t i o n au d e b u t 9 r e t u r n new L i s t e T r i e e ( elem , t h i s ) ;10 else { / / i n s e r t i o n au m i l i e u de l a l i s t e11 L i s t e T r i e e n o u v eau = new L i s t e T r i e e ( elem , r e f ) ;12 p r e d . m o d i f i e R e s t e ( n o u v eau ) ; / / m o d i f i e l e s u i v a n t du p r e d e c e s s e u r13 return t h i s ; / / p r e m i e r e c e l l u l e non m o d i f i e e14 }15 } Variante r´ cursive : e Nous utilisons le mˆ me sch´ ma de d´ composition r´ cursive de la liste, en un premier el´ ment e e e e ´e (premier) et un reste de la liste (reste). L’insertion r´ cursive suit le sch´ ma suivant : e e liste.insertionTriee(e) = ListeTriee(e, liste) si e<=premier liste apr`s reste=ListeTriee(e, null) e si e>premier et reste==null liste apr`s reste=reste.insertionTriee(e) si e>premier et reste!=null e Si l’´ l´ ment a ins´ rer est plus petit ou egal a premier, l’insertion se fera en tˆ te de liste. Sinon, ee ` e ´ ` e l’insertion se fera r´ cursivement dans le reste. Si reste est vide, alors reste sera remplac´ par la nouvelle e e cellule a ins´ rer. Si reste n’est pas vide, l’insertion se fait r´ cursivement dans reste et le r´ sultat ` e e e remplace l’ancien reste. Listing 14.19 – (lien vers le code brut) 1 p u b l i c L i s t e T r i e e i n s e r t i o n T r i e e ( i n t elem ) { 2 i f ( elem <= p r e m i e r ( ) ) 3 r e t u r n new L i s t e T r i e e ( elem , t h i s ) ; 4 else { 5 ListeTriee resteListe = reste (); 6 i f ( r e s t e L i s t e == n u l l ) 7 m o d i f i e R e s t e ( new L i s t e T r i e e ( elem , n u l l ) ) ; 8 else 9 m o d i f i e R e s t e ( r e s t e L i s t e . i n s e r t i o n T r i e e ( elem ) ) ;10 return t h i s ;11 }12 } 14.4.3 Suppression dans une liste tri´ e e La suppression de la premi` re occurrence d’un el´ ment dans une liste tri´ e est assez similaire e ´e e a la suppression dans une liste non tri´ e. La seule chose qui change est la recherche de la cellule a ` e ` supprimer, qui b´ n´ ficie du tri des valeurs. Aussi, si plusieurs occurrences de l’´ l´ ment existent, elles e e ee sont forc´ ment l’une a la suite de l’autre a cause du tri. Il serait donc plus simple d’´ liminer toutes les e ` ` e occurrences de l’´ l´ ment que dans le cas des listes non tri´ es. Nous nous limiterons cependant ici a la ee e ` suppression de la premi` re occurrence seulement. e Variante iterative :
  13. 13. 14.5. UN EXEMPLE DE PROGRAMME QUI UTILISE LES LISTES 13 Par rapport a la m´ thode suppressionPremier de la classe Liste, ici le parcours de la ` e liste a la recherche de l’´ l´ ment ne se fait que tant que ref pointe une valeur plus petite que celui-ci. ` ee Une fois le parcours arrˆ t´ , la seule diff´ rence est qu’il faut v´ rifier que ref pointe vraiment la valeur ee e e recherch´ e. e Listing 14.20 – (lien vers le code brut) 1 p u b l i c L i s t e s u p p r e s s i o n T r i e e ( i n t elem ) { 2 Liste ref=this ; / / r e f e r e n c e qui cherche elem 3 L i s t e pred= null ; / / predecesseur , i n i t i a l i s e a nu l l 4 w h i l e ( r e f ! = n u l l && r e f . p r e m i e r ( ) < elem ) { / / r e c h e r c h e elem 5 pred = r e f ; / / avance pred 6 ref = ref . reste (); / / avance r e f 7 } 8 i f ( r e f ! = n u l l && r e f . p r e m i e r ( ) == elem ) { / / e l e m t r o u v e d a n s l a c e l l u l e r e f 9 i f ( p r e d == n u l l ) / / p r e m i e r e c e l l u l e de l a l i s t e10 return r e f . r e s t e ( ) ; / / r e t o u r n e l e r e s t e de l a l i s t e11 else { / / m i l i e u de l a l i s t e12 p r e d . m o d i f i e R e s t e ( r e f . r e s t e ( ) ) ; / / m o d i f i e l e s u i v a n t du p r e d e c e s s e u r13 return t h i s ; / / p r e m i e r e c e l l u l e non m o d i f i e e14 }15 }16 e l s e return t h i s ; / / e l e m e n t non t r o u v e17 } Variante r´ cursive : e Par rapport a la variante r´ cursive de la m´ thode suppressionPremier de la classe Liste, ` e e une nouvelle condition d’arrˆ t est rajout´ e : e e quand l’´ l´ ment a eliminer est plus petit que premier, il n’existe sˆ rement pas dans la liste et celle-ci ee `´ u est retourn´ e non modifi´ e. e e Listing 14.21 – (lien vers le code brut) 1 p u b l i c L i s t e s u p p r e s s i o n T r i e e ( i n t elem ) { 2 Liste resteListe = reste () ; 3 i f ( elem == p r e m i e r ( ) ) 4 return r e s t e L i s t e ; 5 e l s e i f ( elem < p r e m i e r ( ) ) r e t u r n t h i s ; / / nouvelle condition d ’ arret 6 e l s e i f ( r e s t e L i s t e == n u l l ) r e t u r n t h i s ; 7 else { 8 m o d i f i e R e s t e ( r e s t e L i s t e . s u p p r e s s i o n T r i e e ( elem ) ) ; 9 return t h i s ;10 }11 } 14.5 Un exemple de programme qui utilise les listes Consid´ rons un exemple simple de programme qui manipule des listes chaˆn´ es en utilisant la e ı e classe Liste.
  14. 14. 14 ˆ ´ CHAPITRE 14. LISTES CHAINEES Le programme lit une suite de nombres entiers termin´ e par la valeur 0 et construit une liste avec e ces entiers (sauf le 0 final). La liste doit garder les el´ ments dans l’ordre dans lequel ils sont introduits. ´e Egalement, une valeur ne doit etre stock´ e qu’une seule fois dans la liste. ˆ e Le programme lit ensuite une autre suite de valeurs, egalement termin´ e par un 0, avec lesquelles ´ e il construit une autre liste, sans se soucier de l’ordre des el´ ments. Les el´ ments de cette seconde liste ´e ´e devront etre elimin´ s de la liste initiale. ˆ ´ e A la fin, le programme affiche ce qui reste de la premi` re liste. e Remarque : Pour garder les el´ ments dans l’ordre d’introduction, l’insertion d’un nouvel el´ ment ´e ´e doit se faire en fin de liste. La m´ thode insertionDebut ne convient donc pas. La solution e est d’utiliser la m´ thode concatenation. e Remarque : Pour qu’un el´ ment soit stock´ une seule fois dans la liste, il faut d’abord v´ rifier s’il ´e e e n’y est pas d´ j` , a l’aide de la m´ thode contient. ea ` e Voici le programme qui r´ alise ces actions : e Listing 14.22 – (lien vers le code brut) 1 public cl as s ExempleListes{ 2 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { 3 / / 1. Creation premiere l i s t e 4 T e r m i n a l . e c r i r e S t r i n g l n ( ” E n t r e z l e s v a l e u r s t e r m i n e e s p a r un 0 : ” ) ; 5 Liste l i s t e = null ; / / l i s t e a construire 6 do { 7 i nt val = Terminal . l i r e I n t ( ) ; 8 i f ( v a l ==0) break ; 9 i f ( l i s t e == n u l l )10 l i s t e = new L i s t e ( v a l , n u l l ) ;11 else i f (! l i s t e . contient ( val ))12 l i s t e . c o n c a t e n a t i o n ( new L i s t e ( v a l , n u l l ) ) ;13 } while ( true ) ;1415 / / 2. Creation seconde l i s t e16 T e r m i n a l . e c r i r e S t r i n g l n ( ” V a l e u r s a e l i m i n e r ( t e r m i n e e s p a r un 0 ) : ” ) ;17 Liste l i s t e 2 = null ;18 do {19 i nt val = Terminal . l i r e I n t ( ) ;20 i f ( v a l ==0) break ;21 i f ( l i s t e 2 == n u l l )22 l i s t e 2 = new L i s t e ( v a l , n u l l ) ;23 else l i s t e 2 = l i s t e 2 . insertionDebut ( val ) ;24 } while ( true ) ;2526 / / 3 . E l i m i n a t i o n de l a p r e m i e r e l i s t e27 f o r ( L i s t e r e f = l i s t e 2 ; r e f != n u l l ; r e f = r e f . r e s t e ( ) ) {28 i f ( l i s t e == n u l l ) break ; / / plus rien a eliminer29 l i s t e = l i s t e . suppressionPremier ( r ef . premier ( ) ) ;30 }3132 / / 4. Affichage l i s t e restante33 Terminal . e c r i r e S t r i n g l n ( ” Valeurs r e s t a n t e s : ” ) ;34 f o r ( L i s t e r e f = l i s t e ; r e f != n u l l ; r e f = r e f . r e s t e ( ) )35 Terminal . e c r i r e S t r i n g ( ” ” + r e f . premier ( ) ) ;
  15. 15. 14.5. UN EXEMPLE DE PROGRAMME QUI UTILISE LES LISTES 1536 Terminal . sautDeLigne ( ) ;37 }38 }

×