Exercices
TP1 — Complexités, piles, files et listes
Section intitulée « TP1 — Complexités, piles, files et listes »Le but de cette page est surtout de pouvoir refaire les bons exercices pendant le blocus. On garde donc une courte remise en route théorique, puis uniquement les implémentations qui valent la peine d’être recodées.
Questions d’introduction
Section intitulée « Questions d’introduction »1. ADT et implémentation
Section intitulée « 1. ADT et implémentation »Qu’est-ce qu’un Abstract Data Type (ADT) ? Quelle différence fais-tu entre l’ADT et son implémentation concrète en Java ?
2. Stack avec une linked list
Section intitulée « 2. Stack avec une linked list »Où placer le top dans une singly linked list pour obtenir des push et pop efficaces ? Quelle complexité obtient-on ?
3. Parcours d’une LinkedList
Section intitulée « 3. Parcours d’une LinkedList »Pourquoi ce parcours peut-il être mauvais ?
for (int i = 0; i < list.size(); i++) { process(list.get(i));}Quel pattern faut-il utiliser à la place ?
4. Complexité amortie
Section intitulée « 4. Complexité amortie »Pourquoi un tableau dynamique peut-il avoir un push en amorti, alors qu’un redimensionnement coûte ponctuellement ?
Exercices INGInious à refaire
Section intitulée « Exercices INGInious à refaire »Pendant le blocus, refaire les exercices suivants sans regarder la solution au départ.
StackWithTwoQueues
Section intitulée « StackWithTwoQueues »À refaire entièrement.
Points à maîtriser :
- invariant entre les deux queues ;
- transformation FIFO → comportement LIFO ;
push,pop,peek;- complexité de chaque opération.
SegmentedList
Section intitulée « SegmentedList »À refaire entièrement.
Points à maîtriser :
- indices globaux sur plusieurs segments ;
- parcours d’un segment au suivant ;
- implémentation de
Iterable; - itérateur fail-fast ;
- gestion correcte des cas limites.
CircularLinkedList
Section intitulée « CircularLinkedList »À refaire entièrement.
Points à maîtriser :
- invariant circulaire ;
- manipulation des références ;
enqueue;remove(index);- itérateur fail-fast.
Réponses aux questions d’introduction
Section intitulée « Réponses aux questions d’introduction »Réponse 1
Section intitulée « Réponse 1 »Un ADT définit les données manipulées, les opérations disponibles et leur comportement, sans fixer la représentation interne.
Une implémentation choisit ensuite comment réaliser ce contrat : liste chaînée, tableau dynamique, etc.
Réponse 2
Section intitulée « Réponse 2 »Dans une singly linked list, placer le top en tête permet de modifier seulement quelques références.
node.next = first;first = node;On obtient ainsi push et pop en .
Placer le top en fin peut imposer un parcours pour retrouver le prédécesseur, donc .
Réponse 3
Section intitulée « Réponse 3 »Sur une LinkedList, get(i) peut nécessiter un parcours de la liste. Répéter cet accès pour chaque indice peut donc mener à .
Préférer :
for (E x : list) { process(x);}ou un Iterator, qui parcourt la liste en .
Réponse 4
Section intitulée « Réponse 4 »Quand un tableau dynamique double sa capacité, certains push coûtent , mais ces redimensionnements deviennent de plus en plus espacés.
Les copies successives ont un coût total de l’ordre de :
Sur insertions, le coût total reste donc , soit amorti par insertion.