PDA

Visualizza la versione completa : [C] Eliminazione elemento lista


Satiro88
29-12-2012, 18:49
ciao a tutti,premetto di aver cercato sul forum,il problema è che mi sembrano situazioni troppo avanzate rispetto a quel poco che ho capito,perciò vi posto il mio codice.Ho provato una cosa che dovrebbe essere banalissima,ovvero cancellare un elemento(che io chiamo Nodo) dalla lista:


#include <stdio.h>
#include <stdlib.h>

typedef struct Nd{
int dato;
struct Nd* next;
}Nodo;

int main()
{
Nodo *head;
Nodo *curr;
Nodo *prec;

head=malloc(sizeof(Nodo));
head->dato=3;
head->next=NULL;

curr=malloc(sizeof(Nodo));
curr->dato=4;
curr->next=NULL;
head->next=curr;
prec=curr;

curr=malloc(sizeof(Nodo));
curr->dato=5;
curr->next=NULL;
prec->next=curr;
prec=curr;

curr=malloc(sizeof(Nodo));
curr->dato=6;
curr->next=NULL;
prec->next=curr;

curr=head;
while(curr->next!=NULL)
{
printf("\n%d\n\n",curr->dato);
curr=curr->next;
}
printf("\n%d\n\n",curr->dato);
//ABBIAMO ALLOCATO 4 NODI,ORA PROVIAMO A CANCELLARE IL TERZO

head->next=prec;
curr=prec->next;
prec->next=curr->next;
free(curr);

curr=head;
while(curr->next!=NULL)
{
printf("\n%d\n\n",curr->dato);
curr=curr->next;
}
printf("\n%d\n\n",curr->dato);
system("PAUSE");
return 0;
}


Ricapitolando

alloco 4 nodi e inserisco i dati:

nodo1=3
nodo2=4
nodo3=5
nodo4=6

stampo:

3456

cancello il nodo 3

stampo:

35

qualcosa non va,mi stampa solo il nodo 1 e non capisco perchè il nodo 3 che è quello per cui credevo di aver fatto la free :| sono molto confuso a questo punto.
Attualmente dovrei avere


nodo1 -> nodo2 -> nodo4 -> NULL
*head *prec
*curr

quindi il while dovrebbe stamparli tutti tranne il nodo4...

Grazie a tutti ciao! buone feste!!!!!!

YuYevon
29-12-2012, 20:16
Tieni traccia correttamente dei puntatori. Al termine della creazione della lista, dopo la prima stampa, hai questa situazione:



head -> [3]
[4]
prec -> [5]
curr -> [6]


l'esecuzione di questo codice



head->next=prec;
curr=prec->next;
prec->next=curr->next;
free(curr);


non fa altro che:

1. rendere inaccessibile il secondo nodo (perché al campo next di head associ prec che è il terzo);
2. eliminare dalla lista e deallocare il quarto nodo;

piuttosto, dato lo stato della tua lista, per eliminare il terzo nodo dovresti scrivere:



head->next->next = curr;
free(prec);

Satiro88
30-12-2012, 14:47
sinceramente non credevo nemmeno che esistesse qualcosa come head->next->next,cosa succede scrivendo questo? va al next del next di head? cioè al nodo 3?

è vero curr non ho fatto caso che si sposta con la stampa perchè ogni volta curr=curr->next,quindi si sposta di nodo in nodo

Ah un'altra cosa,ma con curr=head sposto proprio il puntatore? non vorrei aver fatto casino con quello,magari invece mi prende il valore puntato dall'head e lo mette nel nodo puntato da curr

oregon
30-12-2012, 15:34
Originariamente inviato da Satiro88
sinceramente non credevo nemmeno che esistesse qualcosa come head->next->next

E perché non dovrebbe essere possibile? Puoi anche andare oltre ...


va al next del next di head?

E' proprio come appare ...

Satiro88
30-12-2012, 16:04
Grazie comunque alla fine ho risolto,avevo proprio collegato il nodo 2 al prec per poi ribadire che curr era nella posizione curr per poi deallocare.

Avrei un'altra domanda,quanti puntatori posso creare? perchè se ne potessi creare quanti ne voglio diventerebbe molto più facile ma mi sembra fin troppo facile per essere vero :|

oregon
30-12-2012, 16:07
Originariamente inviato da Satiro88
Avrei un'altra domanda,quanti puntatori posso creare? perchè se ne potessi creare quanti ne voglio diventerebbe molto più facile ma mi sembra fin troppo facile per essere vero :|

Non capisco la domanda ... quanti puntatori in che senso?

Satiro88
30-12-2012, 16:29
nel senso,io creo curr head e prec che sono 3 puntatori,posso crearne altri? ad esempio per abbinarli a uno dei tanti nodi nel caso debba fare qualche operazione un pò + complessa,giusto per non impazzire scegliendo dove spostare curr e prec

YuYevon
30-12-2012, 16:36
Se ti stai chiedendo quanti puntatori tu possa dichiarare in un programma, il limite principale che hai è fissato chiaramente dalla memoria che hai a disposizione. Piuttosto che preoccuparti di questo, dato che si tratta di un limite molto ampio, tieni presente che un vincolo molto più stretto è imposto dalla tua salute mentale: quando gestisci una struttura dati non elementare, la cosa migliore da fare per distruggere tutto il più in fretta possibile è cominciare a disseminare puntatori nel codice senza criterio per tenere traccia di questo e di quello. Tutto ciò che ti serve davvero per la gestione di una lista linkata semplice come quella è un puntatore "nodo prossimo" per ciascun nodo e un puntatore alla testa della lista, cioè al primo nodo (a volte anche un puntatore alla coda, cioè all'ultimo nodo, cosa che può semplificare e rendere più performanti alcune operazioni). Tutto qui. Il resto è superfluo, ridondante e peccaminoso.

MItaly
30-12-2012, 16:42
Originariamente inviato da YuYevon
Tutto qui. Il resto è superfluo, ridondante e peccaminoso.
Be' oddio, dipende dall'algoritmo che stai implementando... :D Non ci vedo nulla di male ad avere più puntatori a nodi se effettivamente servono - se, che so, voglio rimuovere degli elementi secondo un certo criterio da una lista concatenata ha senso avere un puntatore che sta sull'ultimo elemento "buono" e uno che va avanti per esaminare gli elementi che seguono, alla ricerca del prossimo elemento da tenere... :stordita:

Satiro88
30-12-2012, 16:57
si penso che mi stiate sopravvalutando,ho provato a inventarmi un esercizio a caso(devo smetterla di inventare esercizi a caso),l'esercizio vuole che io scambi di posto due nodi in una piccola struttura con 5 nodi,in particolare il nodo2 col nodo4:


#include <stdio.h>
#include <stdlib.h>

typedef struct Nd{
int dato;
struct Nd *next;
}Nodo;

int main()
{
Nodo *head;
Nodo *curr;
Nodo *prec;

head=malloc(sizeof(Nodo));
head->dato=10;
head->next=NULL;

curr=malloc(sizeof(Nodo));
curr->dato=20;
curr->next=NULL;
prec=curr;
head->next=curr;

curr=malloc(sizeof(Nodo));
curr->dato=30;
curr->next=NULL;
prec->next=curr;
prec=curr;

curr=malloc(sizeof(Nodo));
curr->dato=40;
curr->next=NULL;
prec->next=curr;
prec=curr;

curr=malloc(sizeof(Nodo));
curr->dato=50;
curr->next=NULL;
prec->next=curr;

printf("\n contenuto dei 5 nodi: \n");
curr=head;
while(curr->next!=NULL)
{
printf("\n %d \n",curr->dato);
curr=curr->next;
}
printf("\n %d \n",curr->dato);

//QUELLO CHE VOGLIO FARE ORA E' SPOSTARE IL NODO 2 CON IL NODO 4
//PER PRIMA COSA PROVO A SPOSTARE IL NODO2 TRA IL 4 E IL 5,PRIMA ASSICURIAMOCI DI COLLEGARE L'1 AL 3

prec=head->next;
head->next=prec->next;
curr=head->next->next;
prec->next=curr->next;
head->next->next=prec;
curr->next=head->next;
head->next=curr;

printf("\n\n ora inverto di posto il nodo 2 con il nodo 4: \n");

curr=head;

while(curr->next!=NULL);
{
printf("\n %d\n",curr->dato);
curr=curr->next;
}
printf("\n %d\n",curr->dato);

system("PAUSE");
return 0;
}

dopo la prima stampa abbiamo:

head-> [1]
prec-> [4]
curr-> [5]

per spostare i due nodi ho fatto questo(o almeno è quello che credevo di fare,corrisponde alla parte appena dopo la "descrizione" nel programma):

- prec->[2]
- [1]->[3] (intendo che collego il nodo1 al nodo3)
- curr->[4]
- [2]->[5]
- [3]->[2]
- [4]->[3]
- [1]->[4]

Deve essere piuttosto difficile per voi senza tutti i disegnini che ho fatto :|,spero si capisca

Il problema è il seguente,da quello che stampa,o meglio da quello che non stampa, non risultano collegati il nodo 4 con il nodo3,ho provato a fargli stampare con un if quelli con curr->next!=NULL e mi stampa solo 10.

Ora sono triste :( ero convintissimissimo

Loading