Listes simplement chaînées

Fermé
Dave1987 Messages postés 7 Date d'inscription jeudi 19 avril 2012 Statut Membre Dernière intervention 10 juillet 2012 - 19 avril 2012 à 13:45
Dave1987 Messages postés 7 Date d'inscription jeudi 19 avril 2012 Statut Membre Dernière intervention 10 juillet 2012 - 25 avril 2012 à 14:57
Bonjour, ma question se porte sur le langage C et plus précisément sur les listes simplement chaînées. Je souhaiterai donc créer une fonction qui permettra de supprimer un élément qui est présent plusieurs fois dans ma liste chaînée.
Par exemple, je suppose que je ne sais pas quel sont les éléments qu'il y a dans ma liste chaînée mais si il y a par exemple un 12 ou plusieurs 12, alors il faut les supprimer.
j'ai essayé avec le programme suivant (ma liste contient 31 31 31 69 31 33 15)

Donc voila la fonction de suppression et d'affichage (pas la peine que je donne les fonctions avec lesquelles j'ai introduit les éléments dans la liste)

langage C
void sup_Multipl(pile *p, int valeur) {
while(p != NULL) {
if(p->val == valeur) {
pile *tmp = p;
tmp = p->next;
free(p);
p = tmp;
}
else {
p = p->next;
}
}
}

langage C
void Afficher_Pile(pile *p) {
pile *afficheur = p;
printf("les elements de la liste sont : \n");
while(afficheur != NULL) {
printf("%d\n", *afficheur);
afficheur = afficheur->next;
}
}

main.C
langage C
pile *Mapile = NULL;
sup_Multipl(Mapile, 31);
printf("Et donc ");
Afficher_Pile(Mapile);


A la compilation j'ai ceci:
0
4007312
4007296
69
4007280
33
15

Donc ma fonction sup_Multipl ne fonctionne pas vraiment puisque les 31 sont supprimés mais il reste toujours des crasses, je pense que c'est dû à la non initialisation après suppression des 31 du pointeur de début de chaîne et des next des éléments non supprimés.
Si quelqu'un peut m'aider ça sera vraiment bienvenue parce que ça fait une semaine que je cherche et j'arrive pas à trouver la solution. MERCI d'avance.

5 réponses

Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
19 avril 2012 à 15:15
Salut
le problème, c'est que tu casses ta liste en supprimant p.
tu arrives à ton maillon de chaine (*p) où tu as la valeur à supprimer. il faut donc que tu supprimes ton maillon et que tu relies le maillon précédent avec le maillon suivant. Et là, dans ta façon de faire tu ne sais plus quel est le maillon précédent, ta chaine est mal reconstruite.
Fait aussi attention à bien prendre en compte les condtions de bord (si le premier maillon est supprimé, ou le dernier)
1
Dave1987 Messages postés 7 Date d'inscription jeudi 19 avril 2012 Statut Membre Dernière intervention 10 juillet 2012
19 avril 2012 à 16:14
d'abord merci d'avoir répondu;
Oui je savais déjà avant la compilation que ma fonction n'allait pas donner le résultat escompté et que le problème vient en effet du fait qu'après suppression des 31, les éléments non supprimés ne sont plus reliés entre eux mais je voulais juste savoir si quelqu'un pouvait me donner la solution directe, lol le code C quoi!
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
19 avril 2012 à 16:46
Qu'on fasse le taf à ta place quoi.
Je te donne au moins la solution : raccorder l'élément précédent avec l'élément suivant par rapport à celui que tu supprimes. un truc du genre :
(p->prec)->next=p->next; free(p);
à toi de modifier ta boucle pour conservé ton p->prec.
0
Dave1987 Messages postés 7 Date d'inscription jeudi 19 avril 2012 Statut Membre Dernière intervention 10 juillet 2012
19 avril 2012 à 20:10
Non pas que je veuille toute la solution mais à force de chercher et de ne rien trouver on a parfois besoin d'un coup de pouce, je ne savais pas d'ailleurs qu'on pouvait écrire ce truc (p->prec)->next
merci pour ton aide Char Snipeur
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
19 avril 2012 à 21:05
oui, mais attention, p->prec n'existe pas, sinon c'est une liste chainé à double direction, et c'est autre chose.
Mais tu peux tout à fait écrire : p->next->next->next tant que la variable existe.
0
Dave1987 Messages postés 7 Date d'inscription jeudi 19 avril 2012 Statut Membre Dernière intervention 10 juillet 2012
24 avril 2012 à 00:38
Salutations;
j'ai oublié de poster un message pour dire que la question est réglée :)
euuuuuuuhhhh j'ai résolu ça en utilisant malheureusement les listes doublement chaînées :( , j'ai essayé avec les listes simples mais je ne suis pas arrivé à chaîner les éléments entre eux après suppression (surtout ceux qui sont situés au milieu).
Merci Char Snipeur pour ton aide
#include <stdio.h>
#include <stdlib.h>

typedef struct listeElement {
    int val;
    struct listeElement *prev;
    struct listeElement *next;
}element;

typedef struct listeRepere {
    size_t length;/
    element *head;
    element *tail;
}liste;

void initialisation(liste *p) {
    p->length = 0;
    p->head = NULL;
    p->tail = NULL;
}

liste *Suppression(liste *p, int valeur) {
    if(p != NULL) {
        element *temp = p->head;
        while(temp != NULL) {
            if(temp->val == valeur) {
                element *sup = temp;
                temp = temp->next;
                if(sup->next == NULL) {
                    p->tail = sup->prev;
                    p->tail->next = NULL;
                }
                else if(sup->prev == NULL) {
                    p->head = sup->next;
                    p->head->prev = NULL;
                }
                else {
                    sup->next->prev = sup->prev;
                    sup->prev->next = sup->next;
                }
                free(sup);
                p->length--;
            }
            else {
                temp = temp->next;
            }
        }
    }
    return p;
}

int main() {
    liste *Mapile = NULL;
    initialisation(Mapile);
    Suppression(&Mapile);
    return 0;
}
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
24 avril 2012 à 08:23
Comme tu as bien travaillé, je te montre une façon de faire (pas testé, donc peut être des bugs)
void sup_Multipl(pile *p, int valeur) {
pile* prec=p;
if(p->val==valeur) 
{
    p=p->next;
    free( tmp);
    sup_Multipl(p,valeur);
    return;
}
while(p->next != NULL) {
  if(p->next->val == valeur) {
    prec= p->next;
    p->next=prec->next;
    free(prec);
  }
  else p = p->next;
}

} 
Je n'ai pas testé, mais ça devrait fonctionner. Sauf qu'il reste un problème, si ton premier élément vaut "valeur", alors tu perds le début de ta liste chainée, mieux vaut passer pile**p afin de modifier la valeur passé en argument.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Dave1987 Messages postés 7 Date d'inscription jeudi 19 avril 2012 Statut Membre Dernière intervention 10 juillet 2012
24 avril 2012 à 21:48
prec tu veux dire tmp, J'ai compris en tous cas ton raisonnement mais il semblerai que ça ne marche pas. même en utilisant pile **p.
ma liste contient 31 31 31 69 31 33 15 avec ta méthode tous est effacés sauf le dernier élément (15), j'ai modifié le else comme suit: p->next =(p->next)->next;
et cette fois ci à la compilation j'ai comme résultat 69 .
mais je vais essayé de réfléchir à ça
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
Modifié par Char Snipeur le 25/04/2012 à 08:25
Oui, en effet encore une erreur, j'ai fait un double raisonnement faux. En fait dans une liste chainée, il faut un debut et un pointeur pour la parcourir.
void sup_Multipl(pile **d, int valeur) { 
pile* prec; 
pile* p=*d; 
if(p->val==valeur)  
{ 
    *d=p->next; 
    free( p); 
    sup_Multipl(d,valeur); 
    return; 
} 
while(p->next != NULL) { 
  if(p->next->val == valeur) { 
    prec= p->next; 
    p->next=prec->next; 
    free(prec); 
  } 
  else p = p->next; 
} 
} 
comme ça, ça devrait aller mieux.
0
Dave1987 Messages postés 7 Date d'inscription jeudi 19 avril 2012 Statut Membre Dernière intervention 10 juillet 2012
25 avril 2012 à 14:57
wawwww, effectivement ça marche super bien, les étapes sont très claires, mais comment tu as fait pour réfléchir comme ça?!!!!!!!!!!!! c'est quoi la logique dans ta tête?!!!!! lol
0