@edgarjacobs: garde précieusement ce lien. @Ashuka: Ça demande une certaine concentration pour implémenter les listes chaînées, surtout les listes doublement chaînées. Je te suggère de prendre du papier et un crayon et de dessiner des schéma représentant les maillons et des flèches montrant vers quoi "pointent" les pointeurs. Portes une attention toute particulière à l'ordre dans lequel tu modifies les pointeurs.
Du coup, j'ai eu le goût de chercher le code pour inverser l'ordre d'une liste doublement chaînée. Les exemples du web ne m'ont pas satisfait. J'ai donc écrit mon propre code. J'ai illustré les structures de maillon et de descripteur de liste. Ça marche même avec une liste vide pourvu que le descripteur de liste existe. - typedef struct Node Node; struct Node { Node *prev; Node *next; int value; }; typedef struct List List; struct List { Node *first; Node *last; int length; }; void reverse(List *list) { Node *node = list->first; list->first = list->last; list->last = node; while(node) {
Dans les cours, on montre comment insérer en début de liste et en fin de liste. On montre aussi comment insérer à une position donnée. Puisqu'on est avec une liste doublement chaînée, on peut chercher la position à partir du début ou à partir de la fin. Par exemple, si on a 351 noeuds dans la liste et qu'on veut insérer avant la position 349, on peut reculer de 2 au lieu d'avancer de 349. (reculer avant 350, avant 349) On numérote généralement les noeuds comme les indices d'un tableau, soit de 0 à N-1. Insérer au début est équivalent à insérer avant la position 0. Insérer à la fin est équivalent à insérer avant la position N. De même, on peut numéroter les noeuds à l'envers. Mais ppuisqu'on ne peut pas écrire -0, on doit commencer à -1 Insérer à la position -1 veut dire insérer à la fin, -2 juste avant le dernier, -N-1 juste avan le premier. On peut écrire une seule fonction qui tient compte de tous ces cas.
Le Tout est souvent plus grand que la somme de ses parties.
Je me refère au message précédent. J'ai utilisé quelques astuces pour coder en une seule fonction tous les cas de figure pour l'insertion. J'en ai fait de même pour la suppression. L'astuce principale est la sttructure de liste et de noeud qui utilisent des union et des sous-structures. On peut se déplacer facilement aussi bien du début vers la fin que l'inverse avec le même code. La position positive ou négative est ajustée pour un déplacement correct. Elle est choisie ainsi que la direction pour le parcours le plus court. Ce code ne vise pas à optimiser la vitesse mais la simplicité du code. La boucle principale fait de 6 à 7 lignes. - #include <stdio.h> #include <stdlib.h>
typedef struct Node Node; struct Node { union { struct { Node *next; Node *prev; }; Node *link[2]; }; int value; }; typedef struct List List; struct List { union { struct { Node *head; Node *tail; }; Node *link[2]; }; int length; };
Les Secrets Que Les Programmeurs Ne Veulent Pas Que Vous Connaissiez (a):
penser systématiquement aux cas-limites : liste vide, un seul élément, début de la liste, fin de la liste, ailleurs. (b)
gribouiller des petits dessins (c) pour trouver l'ordre dans lequel il faut modifier es chaînages (d)
(a) en fait si, ça éviterait de répondre toujours aux même questions
(b) ça ne veut pas dire qu'il y aura 4 cas dans le code : souvent, le même code fait le boulot pour plusieurs cas. Mais il faut s'en assurer.
(c) à l'aide d'un simple crayon et d'un bout de papier, qu'on jette à la poubelle immédiatement après. C'est un outil de travail, pas une oeuvre d'art. Vous devriez toujours avoir un bloc de papier brouillon à côté du clavier (ça sert aussi de tapis souris).
(d) 1. faire deux dessins : la situation de départ, la situation voulue. 2. Ensuite regarder la première opération à effectuer, la dessiner, etc.
On est dans la 3ieme décennie du IIIe millénaire, et ça serait idiot de réimplémenter pour la trouze millième fois une structure de données hyper-classique parce qu'on voudrait s'obstiner mordicus à utiliser un langage des années 60-70 privé de la généricité qui permet d'avoir ça en bibliothèque, écrit une fois pour toutes.
Mais ça c'est pour la production de logiciels. Pour apprendre à programmer, il faut pratiquer en passant par des exercices classiques, qui permettent de se faire la main sur de la petite algorithmique (qui ne pète pas trois pattes à un canard), et aussi de comprendre le fonctionnement interne des "conteneurs" des langages modernes. Toujours utile pour prendre conscience qu'on choisit un conteneur en fonction des opérations qu'on veut lui appliquer, et de leur coût (complexité).
Puisque les pointeurs existent en C, les listes chaînées sont un très bon exercice pour les maîtriser. J'ai écrit du code de fainéant qui ne voulait pas coder une multitude de fonctions.
Le Tout est souvent plus grand que la somme de ses parties.
En Fortran, on pouvait faire plus que des listes chaînées comme un réseau avec l'énoncé equivalence
On pouvait donner des flottants (real) comme valeurs. Utile pour calculer le flot maximum dans un réseau. Au lieu d'avoir des adresses, on avait des indices. C'était commode car les indices devaient commencer à 1 et non 0 reseau(1)=4 indice du noeud suivant reseau(2)=0 pas de précédent reseau(3)=65 valeur reseau(4)=22 noeud suivant reseau(5)=1 noeud précédent reseau(6)=103 valeur ...
- Edité par PierrotLeFou 27 mai 2022 à 18:12:39
Le Tout est souvent plus grand que la somme de ses parties.
Implementation d'une liste doublement chainee en C
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Bonhomme !! | Jeu de plateforme : Prototype.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.