|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
[C]Pila. Pollo io o pollo prof?
Ciao ragazzi. Vorrei farvi questa domanda su un queisto che è uscito nel compito di informatica, sulle strutture dati, precisamente pila. Non mi convince la correzione che il prof ha dato alla mia risoluzione, se vogliamo tralasciare, inoltre, che ha dato la mia medesima soluzione a un problema simile nella dispensa che ci ha fornito.
Comunque veniamo al problema. La traccia era semplice : data una pila di caratteri già generata (non c'è necessita di generare la pila) scrivere una funzione che abbia in ingresso il puntatore alla testa della pila, e che ritorni il puntatore alla testa della pila epurata da tutti gli elementi contenti il campo informazione B. Si scriva inoltre la dichiarazione della struct. Mia soluzione : (ometto la dichiarazione della struct e tutto il pezzo delle dichiarazione di puntatori ausiliari per semplicità). Codice:
p2=NULL; While(puntatesta!=NULL){ if(puntatesta->car=='B')puntatesta=puntatesta->pun; else{ paus=puntatesta; puntatesta=puntatesta->pun; paus->pun=p2; p2=paus; } } While(p2!=NULL){ paus=p2; p2=p2->pun; paus->pun=puntatesta; puntatesta=paus; } Il codice non ha bisogno di commento, nel primo pezzo trasferisco ogni singolo elemento in un altra pila (p2) eliminando gli elementi con campo finroamzioni B, nel secondo pezzo ricostruisco la pila iniziale. Veniamo al dunque, il problema è dove ho messo in grassetto : secondo il prof quel comando fa perdere il puntatore alla testa della pila, e quindi la pila stessa. Secondo lui avrei dovuto fare l'if di controllo una volta estratto ogni singolo elemento, cioè quando l'elemento si trova, da solo, puntato dal puntatore ausiliario paus. Secondo voi chi ha ragione? Io continuo a pensare che, concettualmente, è giusto come ho scritto, anche perchè mi sembra che c'è scritto anche sul libro, se non erro
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2774
|
Ma non potevi usare push e pop?
A parte questo mi sembra giusto. Solo non deallochi gli elementi eliminati, ma forse era richiesto così. |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
Comunque apparte questo, che diavolo è il push e pop? ![]() Pensate che non è riuscito a capire questo pezzo di codice : Codice:
void primalita(int num){ int i=3; if((num==0)||(num==1))printf("\nIl numero non e' primo"); else if(num==2)printf("\nIl numero e' primo"); else if(num%2==0)printf("\nIl numero non e' primo"); else { while(i<num){ if(num%i==0)break; i=i+2; } if(i==num)printf("\nIl numero e' primo"); else printf("\nIl numero non e' primo"); } return; } Io rifarò l'esame per il 23 che ho preso, ma mi sa che visto il prof potrei anche essere bocciato
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Dec 2005
Messaggi: 1278
|
Quote:
EDIT: Il tuo codice potrebbe essere piu' esplicito con l'uso di costanti e nomi piu' espliciti, l'algoritmo mi sembra un po' naive ![]()
__________________
Non esistono grandi uomini, solo grandi ambizioni , realizzate da qualcuno che si è alzato dalla sedia per realizzarle! Ultima modifica di mindwings : 18-01-2010 alle 20:11. |
|
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Il puntatore alla testa lo perdi però dipende da come quel codice è integrato all'interno del resto. Ad esempio: Codice:
void tuafunzione(struct lista * puntatesta) { /*qui ci va il tuo codice*/ } Se io chiamo: struct lista * testa; /* qui riempio la lista */ tuafunzione(lista); /*qui lista non cambia valore */ |
|
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
push e pop non li ho fatti, come non ho fatto qualsiasi operatore che agisca tramite funzione prestabilita in una pila/coda/lista. Cionci, avevo già detto che ho omesso le varie parti del codice per arrivare al problema. ovviamente ho scritto il codice dentro la funzione che tu stesso hai scritto, ovvero Codice:
struct pila *elimina(struct pila *) { } Comunque perchè dici che è una lista? Io elimino sempre il primo elemento e , nella pila ausiliaria, impilo sempre dal primo elemento, e poi faccio l'inverso, quindi direi che non ho "violato" il concetto di pila se non per quell'errore che ha segnato il prof, che ancora sono in dubbio se è sbagliato ralmente o meno. Se poi ho un brutto concetto di pila, non è colpa mia , ma sua ![]()
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
push e pop sono le operazioni di inserimento in testa ed estrazione dalla testa.
Riguardo al codice che hai omesso: ci serviva per capire se effettivamente perdervi il puntatore. Comunque: if(puntatesta->car=='B')puntatesta=puntatesta->pun; Qui non è che perdi il puntatore alla testa, perdi il puntatore a qualsiasi elemento della lista che ha B nel campo informazione. Tu stai usando la pila come se fosse una lista. In teoria le operazioni disponibili sulle liste dovrebbero essere solo push e pop. Quindi non dovresti poter accedere al contenuto interno. Una ricerca come quella che hai fatto si fa con una pila di appoggio in cui andare a mettere tutti gli elementi estratti dalla prima pila (ad esclusione di quelli da rimuovere) per poi rimetterli nella pila originaria. Ultima modifica di cionci : 19-01-2010 alle 11:54. |
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quote:
In pratica io ho fatto cioè che hai detto tu (usato una pila ausiliaria che poi vado a ricostruire), che ho chiamato appunto p2, ma come hai detto tu ho usato un elemento interno nella pila, cosa che è illegale (nell'asegnazione puntatesta=puntatesta->pun, puntatesta->pun si riferisce al secondo elemento della pila, cosa che è improbabile dato che la pila può aver accesso solo al primo elemento). Era la stessa cosa che intendeva il professore quando diceva che perdo la testa, voleva dire che non posso accedere al secondo elemento per la struttura stessa della pila. Grazie mille, mi avete aiutato a capire che cavolo voleva dire il prof con quel "perdi la testa della pila", se me lo avrebbe spiegato come ha fatto cionci, cioè che semplicemente non posso assegnare al secondo elemento, questo 3d non l'avrei nemmeno aperto
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
Quindi ricapitolando, il codice giusto per ottenere una pila epurata dai caratteri B (scusate se non uso questi operatori push e pop, ma come vi ho detto non li ho studiati)
Codice:
struct pila{ char car; struct pila *pun; }; struct pila *elimina(struct pila *puntatesta){ struct pila *paus=NULL, *p2=NULL; while(puntatesta!=NULL){ paus=puntatesta; puntatesta=puntatesta->pun; if(paus->car=='B')free(paus); else{ paus->pun=p2; p2=paus; } } while(p2!=NULL){ paus=p2; p2=p2->pun; paus->pun=puntatesta; puntatesta=paus; } }
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Avevo capito che p2 era la pila ausiliaria...
In questi frangenti si definiscono le due operazioni di push e pop da fare sulla pila in modo da lasciare fare tutto il lavoro a loro. Codice:
struct stack { char info; struct stack * next; }; void push(struct stack ** s, char info) { struct stack * new_head = (struct stack *)malloc(sizeof(struct stack)); new_head->next = *s; new_head->info = info; *s = new_head; } char pop(struct stack ** s) { struct stack * old_head; char ret; if(!*s) return -1; old_head = *s; *s = old_head->next; ret = old_head->info; free(old_head); return ret; } Semplicemente così: Codice:
while((ret = pop(&s)) > 0) { if(ret != 'B') push(&s2, ret); } while((ret = pop(&s)) > 0) push(&s, ret); Ultima modifica di cionci : 19-01-2010 alle 20:30. |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Feb 2004
Messaggi: 1454
|
solitamente (almeno per quanto riguarda la mia esperienza) esercizi del genere vengono assegnati per operare efficientemente ed a basso livello su una struttura dati, non per astrarre tipi da usare con funzioni indipendenti dall'implementazione. appare abbastanza evidente che The-Revenge (e probabilmente, cosa ancor più grave, il suo professore) usi il termine pila per indicare una lista monodirezionale.
una soluzione semplice potrebbe essere questa: Codice:
struct stack { char info; struct stack * next; }; void togliB(struct stack ** s) { struct stack * olds; while (*s) { while (*s->info=='B') { olds=*s; *s=*s->next; delete olds; } s=&(*s->next); } } Ultima modifica di Furla : 20-01-2010 alle 11:41. |
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
![]() E' lo stesso appunto che farei sul secondo codice postato dall'autore del thread, anzi lui si trova in uno stato ancora più incoerente perché usa due pile e poi trasferisce fra le due pile strutture interne della rappresentazione della pila. E' chiaro che fra i due trovo più corretto il tuo approccio, alla fine deve essere uno dei due approcci o quello con l'astrazione (insegna ad usare le pile) o quello che sfrutta la struttura interna a lista (insegna ad usare le liste). Però non è detto che una pila sia organizzata con le liste ![]() In ogni caso perdi la testa della lista...scorri usando *s, quindi alla fine del ciclo *s sarà NULL, ma tale variazione si rifletterà anche sul chiamante. Se vuoi fare una cosa del genere o fai una chiamata ricorsiva o fai un while prima per eliminare gli elementi in testa e poi un altro per gli elementi successivi a quelli in testa. Ultima modifica di cionci : 20-01-2010 alle 11:04. |
|
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Feb 2004
Messaggi: 1454
|
Quote:
*s alla fine del ciclo punterà all'ultimo elemento, che giustamente deve avere next a zero. ovviamente esiste una ricorsiva equivalente, ma non è necessario il doppio ciclo, se si fa uso del puntatore a puntatore. Ultima modifica di Furla : 20-01-2010 alle 13:24. |
|
![]() |
![]() |
![]() |
#14 | |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
PS: scusa, ma ho modificato il post sopra |
|
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Feb 2004
Messaggi: 1454
|
uso tipico:
(scusate se c'è qualche errore ma sono senza compilatore al momento) Codice:
//bla blah void main() { struct stack * testa; struct stack * app; char i =127; while(--i) { // riempio la lista app=(struct stack *)malloc(sizeof(struct stack)); app->info=i; app->next=testa; testa=app; } togliB(&testa); //passo l'indirizzo, non il puntatore alla lista app=testa; while(app){ printf("%c ",app->info); app=app->next; } while(--i) { // riempio la lista app=(struct stack *)malloc(sizeof(struct stack)); app->info=i; app->next=testa; testa=app; } togliB(&testa); //passo l'indirizzo, non il puntatore alla lista app=testa; while(app){ printf("%c ",app->info); app=app->next; } } Ultima modifica di Furla : 20-01-2010 alle 11:57. |
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Certo, dopo la chiamata testa vale NULL, hai quindi perso il puntatore alla testa.
|
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Feb 2004
Messaggi: 1454
|
*s non corrisponde più a testa, alla fine del ciclo.
l'unica possibilità che ho di cambiare testa si verifica quando (e finché, ho fixato) il primo elemento della lista abbia info = B, caso in cui entro nel while interno e assegno a *s (cioè a testa) l'indirizzo dell'elemento successivo. dopodiché s punterà ad un altro puntatore (il next di un elemento successivo) e testa rimarrà invariato. non so se son riuscito a spiegarmi ![]() comunque se hai la possibilità provalo, si vede subito se ho cannato ... Ultima modifica di Furla : 20-01-2010 alle 13:23. |
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
|
![]() |
![]() |
![]() |
#19 |
Senior Member
Iscritto dal: Feb 2007
Messaggi: 1352
|
cionci, mi potresti spiegare perchè il mio codice è sbagliato senza usare push e pop genitlmente? perchè come vi ho detto non li ho studiati, abbiate pazienza con me, anche voi vi siete accorti che chi mi insegna la materia non è il massimo, il libro per la pila ha 2 pagine....
L'unica informazione che vi posso dare è che io uso la pila come una lista da cui si può accedere solo al primo elemento, e anche sul libro fa la stessa cosa. MI potresti dire perchè il codice (il secondo) è sbagliato?
__________________
Ho venduto a : truedocman2004,ragen-fio Ho acquistato da :shinakuma, britt-one |
![]() |
![]() |
![]() |
#20 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Non è sbagliato, il codice funziona.
Diciamo che si trova a metà fra le due strade che si adottano solitamente. Pensa alla tua funzione come appartenente ad una libreria che implementa una pila. In tal caso sicuramente non adotterai il metodo usato da te, ma quello cercherai di sfruttare la struttura a lista andando ad eliminare direttamente gli elementi. Pensa invece alla tua funzione esterna ad un libreria. La libreria ti mette a disposizione un tipo di dato stack e le operazioni di push e pop. Dovrai sfruttare quelle operazioni per andare a risolvere il problema, indipendentemente dalla struttura interna della pila. Il tuo metodo di risoluzione si trova a metà perché trasferisci da una pila all'altra elementi (anche se solo della testa) della struttura interna della pila. Quindi sfrutti e non sfrutti la struttura interna della pila. Sicuramente non mi sembra il miglior approccio di studio. Prova a pensare ad implementare uno stack con un vettore. |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 21:07.