renverser une liste chainée [C] - C - Programmation
Marsh Posté le 27-05-2009 à 08:20:21
Oui, à mon avis c'est impossible car en C on passe des valeurs donc au sortir des fonctions elles sont inchangées et alors headref conserve sa valeur d'origine.
Tu peux par contre avoir un prototype du genre
struct node* headRef Reverse(struct node* headRef)
Marsh Posté le 27-05-2009 à 08:21:31
lejeremy a écrit : Salut à tous,
|
C'est pas possible. Il faut soit
Code :
|
soit
Code :
|
(ou une globale, mais ce n'est plus de la programmation, mais du bricolage).
NOTA : si il s'agit de parcourir une liste chainée à l'envers, je conseille d'étudier ces quelques lignes...
Code :
|
|
Marsh Posté le 27-05-2009 à 14:19:35
Emmanuel Delahaye a écrit :
(ou une globale, mais ce n'est plus de la programmation, mais du bricolage). |
Trap D a écrit : Oui, à mon avis c'est impossible car en C on passe des valeurs donc au sortir des fonctions elles sont inchangées et alors headref conserve sa valeur d'origine. |
Humm, en fait j'ai eu cette question récemment, il doit donc bien y avoir un moyen... (sur l'énoncé il est bien précisé qu'ils veulent struct node*headRef et pas struct node** headRef)
NB: Il est pas demandé de l'afficher mais bien de l'inverser.
en tout cas, merci pour votre aide
[edit] Maintenant que j'y pense, la bonne réponse est peut être, "c'est pas possible"... mais ça serait une question super vache ....
Marsh Posté le 27-05-2009 à 15:02:28
lejeremy a écrit : |
Ah ? C'est un devoir ???
lejeremy a écrit : NB: Il est pas demandé de l'afficher mais bien de l'inverser. |
Il faut d'abord savoir comment est identifiée ta liste. Car il y a 2 façons d'identifier une liste chaînée et ça donne des possibilités différentes pour l'inversion. Et toujours en considérant que "struct node" est un noeud de la liste
1) soit tu possèdes en main l'adresse du premier noeud. Donc tu as un "struct node* first". Or, comme ta fonction d'inversion doit modifier cette adresse (puisque le premier noeud change), il te faut passer l'adresse de l'adresse à la fonction qui recevra donc un "struct node** pt". Une fonction qui modifie une variable doit recevoir l'adresse de la variable et ça c'est incontournable.
2) soit tu possèdes en main une structure qui contient l'adresse du premier noeud. Par exemple un truc de ce style
Code :
|
Ca peut paraître inutile voire idiot de créer une structure qui ne contient qu'un élément que tu pourrais donc tenir directement... sauf que ça permet ensuite de faire évoluer l'objet. Tu peux par exemple ensuite y rajouter une variable qui contiendra le nombre d'éléments, une autre qui contiendra l'élément en cours, une auitre qui contiendra le dernier, bref tout un panel d'outils pour t'aider à gérer ta liste. Ainsi ta structure peut devenir
Code :
|
Et donc toute fonction qui doit manipuler ta liste n'aura qu'à recevoir un "struct liste *pt". Avec ce pt en main, la fonction pourra taper à loisir dans pt->first, pt->last, pt->len et modifier ces variables. Et tu n'as qu'un simple pointeur à gérer et non un double.
Voili voilà.
Marsh Posté le 27-05-2009 à 15:21:33
Sve@r a écrit :
|
Humm pour être honnête c'est une question que j'ai eu lors d'un entretien technique dans une boite (dont je préférerai rester discret sur le nom).
Sve@r a écrit : Il faut d'abord savoir comment est identifiée ta liste. Car il y a 2 façons d'identifier une liste chaînée et ça donne des possibilités différentes pour l'inversion. Et toujours en considérant que "struct node" est un noeud de la liste 1) soit tu possèdes en main une structure qui contient l'adresse du premier noeud. Par exemple un truc de ce style
Et donc toute fonction qui doit manipuler ta liste n'aura qu'à recevoir un "struct liste *pt". Avec ce pt en main, la fonction pourra taper à loisir dans pt->first, pt->last, pt->len et modifier ces variables. Et tu n'as qu'un simple pointeur à gérer et non un double. Voili voilà. |
Pas bête, j'avais pas pensé à changer la structure... Cependant, de mémoire il me semble bien qu'ils demandaient d'utiliser un struct node* et non pas un struct liste ou un truc du genre. Il faut que je leur redemande quand je les vois car vu vos réponses, ça me laisse perplexe...
[edit]j'avais la crêve pendant l'entretien, il se peut que j'ai aussi lu l'énoncé de travers.
Marsh Posté le 27-05-2009 à 19:58:09
lejeremy a écrit : Pas bête, j'avais pas pensé à changer la structure... Cependant, de mémoire il me semble bien qu'ils demandaient d'utiliser un struct node* et non pas un struct liste ou un truc du genre. Il faut que je leur redemande quand je les vois car vu vos réponses, ça me laisse perplexe... |
Autre solution à laquelle je n'ai pas pensé => tu ne modifies pas les adresses de tes noeuds... mais leur contenu.
Ainsi le contenu du premier noeud permute avec celui du dernier, celui du second avec celui de l'avant dernier etc.
Ca se fait à coup de memcpy en passant par un noeud intermédiaire et donc la fonction qui fait ça recevra un "struct node *" correspondant au premier noeud de la liste...
Je n'y ai pas pensé de suite tellement ça me parait con (vaut mieux permuter 2 adresses de 4 octets que 2 structures de taille inconnue (8Gb ???)) mais bon, si c'est imposé...
Marsh Posté le 28-05-2009 à 21:33:01
Bon j'ai enfin la solution... Moi aussi j'étais passé totalement à côté qu'on pouvait copier manuellement le contenu des nodes.
Alors premièrement, on inverse la liste à partir du deuxième node comme dans le premier cas.
Ensuite, on switch manuellement le dernier caractère (copie manuelle) dans headRef et on le fait pointer bien où il faut. On fait aussi pareil en faisant pointer le dernier de la chaîne vers NULL (fin de liste chainée).
Je posterai ma solution en code demain si il y en a qui sont intéressés.
merci à tous ceux qui ont essayer de me répondre
a+
Marsh Posté le 29-05-2009 à 10:52:21
lejeremy a écrit : Bon j'ai enfin la solution... |
Je ne vois pas comment tu vas modifier le "head" original ...
Marsh Posté le 29-05-2009 à 15:59:50
Comme promis, voici le code source:
(avec un schéma, c'est beaucoup plus facile à comprendre).
Code :
|
Code :
|
voilà voila
Marsh Posté le 29-05-2009 à 16:13:30
lejeremy a écrit : Comme promis, voici le code source: (avec un schéma, c'est beaucoup plus facile à comprendre).
|
Je n'ai toujours pas compris comment tu modifiais headRef...
http://www.bien-programmer.fr/note [...] e_variable
Montre ton code de test.
Marsh Posté le 29-05-2009 à 16:15:06
Code :
|
Marsh Posté le 29-05-2009 à 16:24:36
lejeremy a écrit : <code> |
Oui, je vois. La liste est inchangé, mais le contenu est modifié. C'est la pire des solutions sur le plan de l'efficacité. elle va à l'encontre d'un principe sage qui veut qu'on ne touche jamais aux données, mais au chainage... Qui dit que les données ont la même taille (on peut chainer n'importe quoi...)
Bref, cette contrainte absurde sur le prototype fait générer un code absurde et inutilisable. J'espère que le prof fera la remarque...
Marsh Posté le 29-05-2009 à 16:29:17
En fait, je sais pas si tu as regardé, mais au final on change le contenu seulement pour 2 maillons de la chaine. Pour les autres on inverse classiquement les pointeurs. Et encore une fois, c'est pas pour un prof mais c'était pour un entretien technique dans une boite.
Toujours est-il que moi aussi je suis passé carrément à côte de la solution au début.
Marsh Posté le 29-05-2009 à 16:34:17
lejeremy a écrit : En fait, je sais pas si tu as regardé, mais au final on change le contenu seulement pour 2 maillons de la chaine. Pour les autres on inverse classiquement les pointeurs. Et encore une fois, c'est pas pour un prof mais c'était pour un entretien technique dans une boite. Toujours est-il que moi aussi je suis passé carrément à côte de la solution au début. |
Eh bé. Si cette boite attend ce genre de solution technique, ça fait peur... Sans dec, si les données n'ont pas la même tallle, ça va être chaud... Il existe des structures de données comme ceci :
Code :
|
mappés sur une zone mémoire de taille adéquate (et oui, c'est portable. Cette 'astuce' a même été entérinée en C99 sous la forme :
Code :
|
).
Marsh Posté le 30-05-2009 à 12:32:50
lejeremy a écrit : Toujours est-il que moi aussi je suis passé carrément à côte de la solution au début. |
C'est naturel. Seul un gros débile ou un très débutant y aurait pensé d'instinct. Et en plus Emmanuel a fait une bonne remarque en disant qu'on peut chaîner n'importe quoi car la solution de permut des data suppose que les data sont de même nature (ou au pire de même taille).
Emmanuel Delahaye a écrit : Eh bé. Si cette boite attend ce genre de solution technique, ça fait peur... |
Ouaip. Ou alors ils cherchent le cas le plus tordu pour voir jusqu'où peut aller le candidat pour répondre au problème imposé.
Emmanuel Delahaye a écrit : Il existe des structures de données comme ceci :
|
Euh... je ne comprends pas le rôle de ce genre de structure, ni pourquoi data n'est pas un simple pointeur ???
Marsh Posté le 26-05-2009 à 20:09:04
Salut à tous,
J'ai besoin de renverser une liste chainée classique en C. J'ai trouvé un truc classique qui marchait bien:
Maintenant, je cherche à faire la même fonction Reverse mais avec pour prototype void Reverse(struct node* headRef) (et pas void Reverse(struct node** headRef)). Des idées ?