|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9431
|
Liste: alcune operazione non le capisco
Ciao ragazzi
mi aiutate per favore con le operazioni sulle liste alcune non le capisco Anzitutto vi posto l'intestazione Codice:
// LISTADI1.H : Implementazione dinamica della struttura astratta lista
// realizzata con libreria di funzioni. File di SPECIFICA
#ifndef _LISTA_H_ // Compilazione condizionale
#define _LISTA_H_
typedef int E; // Def. del tipo di el. della lista
struct Record; // Predichiarazione
typedef Record* L; // Def. del tipo puntatore a Record
struct Record { // Tipo record costituito da
E elem; // campo informazione
L punt; // campo puntatore al prossimo nodo della lista
};
void start(L& l); // Inizializza la lista
bool empty(const L& l); // Test di lista vuota
bool full(const L& l); // Test di lista piena
void insert(L& l, const E & e); // Inserimento in coda
bool erase(L& l, const E & e); // Cancellazione di un elemento specificato
bool inlist(const L& l, const E & e); // Vera se e e' presente nella lista
void print(const L &l); // Stampa la lista
void clear(L & l); // Distrugge la lista
#endif
-il contenuto (elem ) -puntatore (punt) ed l di tipo L che è puntatore alla testa della lista Poi vi metto l'implementazione Codice:
// LISTA.CPP : Implementazione dinamica della struttura lista con
// libreria di funzioni. File di IMPLEMENTAZIONE
#include "lista1.h"
#include <iostream>
using namespace std;
//------------------------------------------------------------
void start(L& l) {
l=0;
}
//------------------------------------------------------------
bool empty(const L& l) {
return (l==0);
}
//------------------------------------------------------------
bool full(const L& l) {
return false;
}
//------------------------------------------------------------
void push(L& l,const E & e) {
L q=new Record; //alloca spazio
q->elem=e; //vi pone e
q->punt=l; //lega al resto della lista
l=q; //lo mette in testa alla lista
}
//------------------------------------------------------------
// insert versione iterativa
void insert(L& l,const E & e) {
if(l==0 || l->elem>e) push(l,e); //l'elemento va inserito in testa
else { //l'elemento va inserito al centro o in coda
L prec=l, succ;
//alloca ed inizializza il nuovo elemento
L q=new Record;
q->elem=e;
q->punt=0;
while(prec->punt && prec->punt->elem<e ) prec=prec->punt; //determina prec
succ=prec->punt; //determina succ, se l'inserimento è in coda succ deve valere 0
// collega il nuovo elemento al resto della lista (anche in coda se è il caso)
q->punt=succ;
prec->punt=q;
}
//------------------------------------------------------------
void pop(L& l,E& e) { //oppure: bool pop(L& l,E& e)
e=l->elem; // copia in e il primo elemento
L p=l; // salva il valore di l
l=l->punt; //aggiorna l
delete p; // dealloca il primo elemento
}
//------------------------------------------------------------
// lastpop versione iterativa
void lastpop(L& l,E& e) { //oppure: bool lastpop(L& l,E& e)
if(l->punt==0) pop(l,e);
else {
L temp=l;
while(temp->punt->punt) temp=temp->punt; //scorre la lista, si ferma sul penultimo elemento
e=temp->punt->elem; // copia in e l'ultimo elemento
L p=temp->punt; // salva l'indirizzo dell'ultimo elemento
temp->punt=0; // "stacca" l'ultimo elemento dalla lista
delete p; // dealloca l'ultimo elemento
}
}
//------------------------------------------------------------
// inlist: ricerca sequenziale versione iterativa
bool inlist(const L& l,const E & e) {
L temp=l;
bool trovato=false;
while (temp && !trovato) {
if (e==temp->elem) trovato=true;
else
temp=temp->punt;
}
return trovato;
}
//------------------------------------------------------------
// stampa versione iterativa
void print(const L & l) {
L temp=l;
while(temp) {
cout << temp->elem;
cout << "\t";
temp=temp->punt;
}
}
Codice:
//------------------------------------------------------------
void push(L& l,const E & e) {
L q=new Record; //alloca spazio
q->elem=e; //vi pone e
q->punt=l; //lega al resto della lista
l=q; //lo mette in testa alla lista
}
//------------------------------------------------------------
Poi assegno q ad l, in modo tale che il puntatore alla testa della lista punti al nuovo record creato poi la funzione inserimento Codice:
// insert versione iterativa
void insert(L& l,const E & e) {
if(l==0 || l->elem>e) push(l,e); //l'elemento va inserito in testa
else { //l'elemento va inserito al centro o in coda
L prec=l, succ;
//alloca ed inizializza il nuovo elemento
L q=new Record;
q->elem=e;
q->punt=0;
while(prec->punt && prec->punt->elem<e ) prec=prec->punt; //determina prec
succ=prec->punt; //determina succ, se l'inserimento è in coda succ deve valere 0
// collega il nuovo elemento al resto della lista (anche in coda se è il caso)
q->punt=succ;
prec->punt=q;
if (il puntatore alla testa della lista è =0 oppure il campo elemento acceduto dal puntatore alla testa della lista è >e valore presente nel campo elemento del record) fai push mettendo il record in testa. else considera il puntatore a record "prec" inizializzato a quello di testa, e un altro puntatore a record "succ" crea nuovo record, puntato da q , ed assegna ai due campi del nuovo record "e" e "0". while( prec accede a punt ,secondo campo del record, e prec accede a punt che accede ad elemento del record successivo che sia < e ) cioè faccio scorrere prec, giusto? assegna a prec il puntatore e a succ il puntatore acceduto con prec. assegna al secondo campo acceduto da q (quella del nuovo record) "succ" e al campo punt acceduto da prec assegna q. queste non le ho capite. Mi aiutate per favore
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2776
|
Quote:
Non essendoci le parentesi graffe dopo il while, l'istruzione che viene ripetuta è solo quella immediatamente successiva. Inoltre la condizione prec->punt è equivalente a scrivere prec->punt != 0 (cioè prec->punt != null). Codice:
while(prec->punt && prec->punt->elem<e ) prec=prec->punt; //determina prec Codice:
succ=prec->punt; //determina succ, se l'inserimento è in coda succ deve valere 0
// collega il nuovo elemento al resto della lista (anche in coda se è il caso)
q->punt=succ;
prec->punt=q;
|
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9431
|
Quote:
" prec->punt è equivalente a scrivere prec->punt != 0 " che sta a significare che finchè prec non accede al puntatore di coda? però non dovrebbe essere quello scritto nella parentesi del while a scorrere la lista? il problema credo che sia proprio qui: non capisco le parentesi del while e le due istruzioni precedenti prec=prec->punt; succ=prec->punt; cmq in generale quindi le cose che ho scritto per le cose che ho sottolineato vanno bene? devo solo capire a cosa servono ognuna
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. Ultima modifica di Bandit : 28-05-2012 alle 11:00. |
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2776
|
Secondo me stai ragionando troppo a basso livello. Ok capire le istruzioni però dopo che hai capito quello che fanno devi capire cosa fanno nel complesso. Quello che fa la funzione di insert è un inserimento ordinato, ad esempio nella lista
13 -> 45 -> 107 -> 112 Voglio inserire 53 la funzione inizialmente mette in prec la testa della lista, dopodiché il ciclo mette in prec gli elementi successivi, finché non giungo o alla coda (è la condizione prec->succ != null) o ad un elemento maggiore dell'elemento che voglio inserire (è la condizione prec->punt->elem<e). Nell'esempio, alla fine del ciclo prec conterrà il riferimento a 45. Codice:
succ=prec->punt;
q->punt=succ;
prec->punt=q;
- metto in succ l'elemento successivo (se prec punta alla coda prec->punt varrà null). Nell'esempio succ punta a 107 - imposto succ come successore dell'elemento che sto inserendo - imposto l'elemento che sto inserendo come successore di prec Risultato: 13 -> 45 -> 53 -> 107 -> 112 |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9431
|
il fatto è che se lo devo riprodurre lo devo capire
e purtroppo non l'ho capito ancora. Come mi immagino prec e succ? il primo è un puntatore che inizializzo alla testa della lista. il secondo che ne faccio? come si muove? il while () mi dice che : mentre il puntatore prec accede ai secondi campi dei record, e fino a che questi puntano ad un primo campo del record < del primo campo del nuovo record. concordi? finchè avviene tutto ciò, " prec=prec->punt " cioè assegno a prec i secondi campi dei record che son diversi da zero e con " succ=prec->punt " assegno a succ i secondi campi dei record. E da qui nasce la domanda: come si differenziano i due puntatori prec e succ? dopo questa istruzione non sono uguali? però poi le due ultime istruzioni : -assegnano succ al secondo campo del record nuovo -assegnano q al secondo campo del record nuovo cmq non mi torna Provo ad inserire questae append che inserisce in coda avendo un il solo puntatore temp ma cmq non mi è tanto chiaro Codice:
// append versione iterativa
void append(L& l,const E & e) {
if(l==0) push(l,e);
else {
L temp=l;
L q=new Record; //alloca spazio
q->elem=e; //vi pone e
q->punt=0; // e' l'ultimo elemento della lista
while(temp->punt) temp=temp->punt; //scorre la lista, si ferma sull'ultimo elemento
temp->punt=q; //lo mette in coda alla lista
} //fine if
}
oppure inizializza un altro puntatore a record "temp" al puntatore in testa, e crea un altro record q nel quale setto i due suoi campi a "e" e "0"; mentre "temp" accede al secondo campo dei record, assegna a temp il secondo campo dei record. Ma che vuol dire questo? nei commenti c'è scritto che si ferma all'ultimo elemento e perchè? assegna q (il puntatore del nuovo record) a temp, in modo da metterlo in coda
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. Ultima modifica di Bandit : 28-05-2012 alle 17:22. |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2776
|
Tanto per cominciare ti consiglio di chiamare i campi del record con i loro nomi: elem e punt. Sai che elem è il valore dell'elemento della lista, mentre punt è il puntatore all'elemento successivo (se ce n'è uno). Purtroppo la scelta dei nomi dei campi non è stata particolarmente felice... In modo più chiaro avresti potuto chiamarli value e next (o valore e successivo).
Poi mi sembra di capire che non hai compreso ancora come si legge il while. In generale il while è fatto così: Codice:
while(condizione)
{
istruzioni //Questo è il corpo del ciclo (ciò che viene ripetuto finché condizione è vera)
}
Codice:
while(prec->punt && prec->punt->elem<e ) prec=prec->punt; succ=prec->punt; q->punt=succ; prec->punt=q; Codice:
while(prec->punt && prec->punt->elem<e )
{
prec=prec->punt;
}
succ=prec->punt;
q->punt=succ;
prec->punt=q;
prec e succ sono variabili di utilità: nella prima vorresti avere il puntatore all'elemento che precederà quello che stai inserendo: Codice:
L prec=l; //prec viene inizializzato alla testa
while(prec->punt && prec->punt->elem<e )
{
prec=prec->punt; //prec si sposta in avanti finché è necessario
}
Codice:
succ=prec->punt; Codice:
q->punt=succ; prec->punt=q; Provo a spiegarti ancora una volta il ciclo while perché rileggendo meglio il tuo post mi sembra che non hai capito una cosa fondamentale: Poniamo di avere la lista 13 -> 45 -> 107 -> 112 Voglio inserire 53 Simuliamo passo passo cosa fa il codice seguente, ponendo che l è il puntatore alla testa (cioè all'elemento che contiene 13) e che e sia il valore intero 53. Codice:
L prec=l; //prec viene inizializzato alla testa
while(prec->punt && prec->punt->elem<e )
{
prec=prec->punt; //prec si sposta in avanti finché è necessario
}
succ=prec->punt;
- Viene controllata la condizione del while: - Viene eseguito il corpo del while, quindi in prec viene messo prec->punt. Al termine di questa istruzione prec non punta più a 13 ma a 45. - Viene controllata la condizione del while: - Il ciclo while termina e si passa all'istruzione successiva - In succ viene messo prec->punt, quindi al termine di questa istruzione succ punterà a 107. prec continuerà a puntare a 45. Ultima modifica di wingman87 : 29-05-2012 alle 09:23. Motivo: Ho scritto un numero al posto di un altro |
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9431
|
Quote:
questa frase è sbagliata la corretta è - In succ viene messo prec->punt, quindi al termine di questa istruzione succ punterà a 107. prec continuerà a puntare a 45. giusto?
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2776
|
Hai ragione, è un errore. Ora ho corretto.
Ora ti è più chiaro quel codice? |
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9431
|
Credo di si
allora ricapitolo solo a parole considero 5 -10- 15- 20 e voglio inserire 12 in prec metto il puntatore all'elemento che contiene 5 (testa della lista) Ora metre prec accede ai punt e e mentre accede a punt che accedono ai campi elem < 12 , fai accedere prec ai punt (cioè scorri la lista) Arrivati a 12, si ricontrolla il while ed una condizione viene meno poichè 15<12 e quindi termina ciclo while e succ punta a 10. In succ (che è una variabile puntatore) metto puntatore al successivo rispetto a quello che voglio inserire (succ lo faccio puntare a 15). faccio in modo che l'elemento che voglio inserire abbia come punt, succ |12 | succ| faccio in modo che l'elem che viene puntato da prec (10) abbia come punt q cioè |10|q|
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2776
|
Anche se non mi piace molto come lo hai descritto mi sembra che hai capito.
Quote:
E qui avrei detto: quando prec giunge a 10 una condizione viene meno poichè 15<12 (15 è prec->punt->elem) e quindi termina il ciclo while con prec che punta a 10. |
|
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9431
|
non ho usato il termine successore, poichè il si potrebbe confondere con succ.
così facendo chiamando il secondo campo col suo nome (punt) mi è + chiaro grazie mille il tuo aiuto è stato prezioso
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. Ultima modifica di Bandit : 29-05-2012 alle 19:51. |
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Sep 2003
Messaggi: 9431
|
ciao Wing
ti posso richiedere una manina su una parte di programma che prevede l'uso di una coda che permetta all'utente di inserire una transazione, eliminarla e stampare la sequenza di transazioni? questa è l'intestazione e non ci son problemi first è il puntatore alla coda che viene posizionato alla testa della coda dal costruttore della classe CodaTransazioni Codice:
#ifndef _CODATRANSAZIONI_H_
#define _CODATRANSAZIONI_H_
#include "Soggiorno.h"
struct Nodo
{
Transazione*T; //il nodo composto da due campi: T e next
Nodo*next;
};
class CodaTransazioni
{
private:
Nodo*first;
public:
CodaTransazioni(){first=0;}
bool Empty(){return first==0;}
bool Append(Transazione*);
bool Pop();
bool StampaCoda();
bool MemorizzaTransazioni();
~CodaTransazioni();
};
#endif
1 Questa funzione inserisce una transazione nella coda e mi dice che: SE la coda è diversa da vuota allora -crea un altro puntatore alla struttura Nodo e lo inizializza a first, in modo da puntare alla testa della coda. -while (questo puntatore temp accede al campo next diverso da 0, quindi non elemento di fine coda) , fai accedere tempo ai prossimi campi next -temp che accede al campo next ponilo come nuovo nodo??? (questa è strana) -setta i campi di questo nuovo nodo con next =0 e T=Tr dove Tr è il parametro passato alla funzione Append stessa -poni vero in esito, cioè è avvenuto l'inserimento questo insomma fa l'inserimento in cosa, giusto? OPPURE -crea nuovo nodo e mettilo in first -setta i campi del nuovo nodo con tr e 0 -esito è positivo , poichè è avvenuto l'inserimento. questo fa l'inserimento del primo elemento nella coda giusto? Codice:
#include "CodaTransazioni.h"
bool CodaTransazioni::Append(Transazione*Tr)
{
bool esito=false;
if(!Empty())
{
Nodo*temp=first;
while(temp->next!=0) temp=temp->next;
temp->next=new Nodo;
temp->next->next=0;
temp->next->T=Tr;
esito=true;
}
else
{
first=new Nodo;
first->next=0;
first->T=Tr;
esito=true;
}
return esito;
}
SE la coda è diversa da vuota -crea un puntatore a Nodo, e lo inizializza a first (testa della coda) -mette in first, first che accede ai successivi elementi (questa è strana) -cancella temp io non ho capito a che serve instanziare temp Codice:
bool CodaTransazioni::Pop()
{
if(!Empty())
{
Nodo*temp=first;
first=first->next;
delete temp;
return true;
}
else return false;
}
3 -crea sempre il solito puntatore temp a nodo, inizializzato alla testa della coda -while (temp è diverso da 0, cioè non accede alla fine della coda , giusto?) questa non l'ho capita Codice:
CodaTransazioni::~CodaTransazioni()
{
Nodo*temp=first;
while(temp!=0)
{
temp=first->next;
delete first;
first=temp;
}
first=0;
}
questa dovrebbe accedere tramite temp al campo T degli elementi della coda , e tramite T che è oggetto della classe Transazioni, richiamare la funzione stampaDati della classe transazioni. Però non ho capito perchè dopo aver richiamato la funzione c'è una tal funzione temp=temp->next; Codice:
bool CodaTransazioni::StampaCoda()
{
if(!Empty())
{
Nodo*temp=first;
while(temp!=0)
{
temp->T->StampaDati();
temp=temp->next;
}
return true;
}
else return false;
}
questa funzione secondo il testo dovrebbe essere una funziona che invocata su un oggetto di classe coda, scrive su file di tipo testo i dati relativi a tutte le transizioni in coda......questa me ne preoccuperei dopo Codice:
bool CodaTransazioni::MemorizzaTransazioni()
{
if(!Empty())
{
Nodo*temp=first;
while(temp!=0)
{
temp->T->StampaSuFile();
temp=temp->next;
}
return true;
}
else return false;
}
__________________
1)P4 2.4-Asrock p4i65- Sapphire Hd3450 512mb agp- 2GB ddr400-Hd 80gb WD- Thermaltake Litepower 450W 2)Amd 3200-Msi K8n Neo4 Platinum - 2*512 MB pc3200-Asus N6600gt- HD WD 160GB-enermax noisetacker 370. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 11:19.




















