Oppure

Loading
30/07/12 10:53
fabioser
Salve a tutti, utenti e moderatori del Forum. Chiedo aiuto nella soluzione di un semplice problema. Si tratta di stampare in uscita una lista di interi ordinata in senso crescente, a partire da una lista data in ingresso, costituita da numeri interi tutti diversi tra loro. La soluzione che ho elaborato, per quel che riguarda la procedura di calcolo della lista ordinata di cui sopra, fa uso di due cicli while, l'uno annidato nell'altro, con il più interno che confronta via, via, i singoli elementi della lista con gli n,n-1,...,1 elementi successivi, per determinare i massimi che verranno inseriti in testa alla lista ordinata dal più grande al più piccolo.Tuttavia tale soluzione, quando vado ad eseguire il programma risolutivo da me elaborato, mi dà errore 216. Credo che ciò sia dovuto al fatto che nel ciclo più interno di questa procedura il ciclo while tenta l'accesso a valori di p=nil. Qualcuno tra voi è in grado di indicarmi la soluzione esatta, e segnalarmi eventuali errori? Riporto di seguito il codice del programma che ho compilato:


program ListaOrdinataInSensoCrescente(input,output);
const bell=07;
type punt=^elem;
     elem= record
                 val  : integer;
                 next : punt;
           end;
var p,lista : punt;
    n,max,risposta : integer;

procedure LeggiLista( var p : punt; k : integer);
begin
     if k=0
     then p:=nil
     else begin
               new(p);
               read(p^.val);
               LeggiLista(p^.next,k-1);
          end;
end;{fine procedura LeggiLista}
procedure OrdinamentoLista( var p,lista : punt);
begin
     {creo la lista degli elementi ordinati}
     new(lista);
     {il primo elemento di tale lista lo pongo uguale al primo della lista p
     ed eventualmente se non è il più grande di p lo aggiornerò}
     lista^.val:=p^.val;
     while p<>nil
     do begin
             {inizializzazione del valore del massimo della lista in ingresso}
             p^.val:=max;
             p:=p^.next;
             {confronto via via degli elementi di p con tutti i loro successivi
             e aggiornamento della variabile max}
             while p<>nil
             do begin
                     if p^.val>max
                     then max:=p^.val;
                     p:=p^.next;
                end;
             {inserimento dell'elemento max ( che è il più grande via via tra gli n,n-1,..,1
             elementi di p ) in testa alla lista ordinata così in senso crescente}
             lista^.val:=max;
             {aggionamento dell'elemento lista}
             lista:=lista^.next;
             {aggiornamento di p}
             p:=p^.next;
        end;
end;{fine procedura OrdinamentoLista}
{corpo del programma}
begin
     repeat
           writeln('--------------------------- Dati di ingresso --------------------------------');
           writeln;
           writeln;
           write('Fornire la dimensione della lista: ');
           readln(n);
           if n>20
           then begin
                     writeln(chr(bell),'Errore nei dati di ingresso! - STOP -');
                     exit;
                end
           else begin
                     writeln;
                     writeln;
                     writeln('Fornire la lista in ingresso:');
                     writeln;
                     writeln;
                     LeggiLista(p,n);
                     writeln;
                     writeln;
                     OrdinamentoLista(p,lista);
                     writeln;
                     writeln;
                     while(lista<>nil)
                     do begin
                             write(lista^.val:3,' ');
                             lista:=lista^.next;
                        end;
                end;
                writeln;
                writeln('Finito?');
                writeln;
                writeln;
                writeln('Scrivere 1 per terminare 2 per continuare');
                writeln;
                writeln;
                readln(risposta);
     until(risposta=1);
     readln;

end.




Ringraziando da ora chiunque saprà fornirmi la soluzione corretta vi saluto tutti. Ciao!!!:)
aaa
30/07/12 15:27
gigisoft
Ciao, c'e' un errore nella procedura LeggiLista in quanto di volta in volta il p^.Next non viene realmente aggiornato; potresti modificarla così:

Function LeggiLista(k : integer): punt;
var p : punt
begin
     if k=0
     then p:=nil
     else begin
               new(p);
               read(p^.val);
               p^.Next := LeggiLista(k-1);
          end;

     LeggiLista := p;

end;{fine procedura LeggiLista}


e ovviamente nel programma principale la chiamerai cosi':

p := LeggiLista(n);


Ciao. :k:
aaa
30/07/12 15:52
fabioser
Ti ringrazio per il suggerimento. Ma io vorrei sapere se qualcuno di voi è in grado di segnalarmi l'errore nella procedura OrdinamentoLista. Forse va introdotta una variabile ausiliaria in modo da non incorrere nella chiamata di p=nil nel ciclo while più interno? E se sì, potresti formulare la risposta corretta in codice? Te ne sarei infinitamente grato...
aaa
30/07/12 16:15
gigisoft
intanto correggi la funzione LeggiLista come ti ho detto, perche' con quella che hai fatto tu ti ritrovi i valori dei p^.Next tutti sballati, e questo ti impedisce il corretto funzionamento della lista

Inoltre vedo ora che nella procedura di ordinamento fai per tutti e due i cicli innestati il controllo sulla stessa variabile (p), e gia' questa e' una cosa da non fare mai, poi noto che il metodo che usi per 'ordinamento e' totalmente sbagliato, non so che metodo avevi intenzione di implementare, ma sicuramente il codice che hai usato non funziona per niente, ti consiglio di riguardarti un po' di algoritmi di ordinamento.

Ciao. :k:
aaa
30/07/12 16:28
fabioser
Credo che l'errore sia nel punto seguente

while p<>nil
             do begin
                     if p^.val>max
                     then max:=p^.val;
                     p:=p^.next;
                end;



poichè una volta individuato il valore di max per i vari n,n-1,..,1 elementi,questo vada via via estratto dalla lista di partenza p e posto in testa a lista e per questo credo sia necessario introdurre una variabile puntatore ausiliaria...
aaa
30/07/12 16:47
fabioser
O.K., hai perfettamente ragione. Non mi ero reso conto della gravità dell'errore; cercherò di seguire i tuoi consigli e riscrivere completamente la procedura OrdinamentoLista...Grazie comunque!!!
aaa
31/07/12 9:43
fabioser
Ho provato a riscrivere la procedura OrdinamentoLista. Tuttavia incontro due difficoltà : a) L'estrazione dei vari massimi via via decrescenti, dalla lista p ed il loro inserimento nella variabile 'lista'.
b) l'uso di un'altra variabile q per rappresentare la lista data in ingresso,nel ciclo while più interno.
Il codice del programma, che tuttavia così com'è non funziona, tenuto conto anche dei suggerimenti proposti è il seguente:


program ListaCrescente(input,output);
    const bell=07;
    type punt=^elem;
         elem= record
                     val  : integer;
                     next : punt;
               end;
    var p,lista : punt;
        n,max,risposta : integer;

    Function LeggiLista(k : integer): punt;
    var p : punt ;
    begin
         if k=0
         then p:=nil
         else begin
                   new(p);
                   read(p^.val);
                   p^.Next := LeggiLista(k-1);
              end;
     
         LeggiLista := p;
     
    end;{fine function LeggiLista}
    procedure OrdinamentoLista( var p,lista : punt);
    var q : punt;
    begin
         {creo la lista degli elementi ordinati}
         new(lista);
         {il primo elemento di tale lista lo pongo uguale al primo della lista p
         ed eventualmente se non è il più grande di p lo aggiornerò}
         lista^.val:=p^.val;
         while p<>nil
         do begin
                 {inizializzazione del valore del massimo della lista in ingresso}
                 p^.val:=max;
                 p:=p^.next;
                 q:=p;
                 {confronto via via degli elementi di p con tutti i loro successivi
                 e aggiornamento della variabile max}
                 while q<>nil
                 do begin
                         if q^.val>max
                         then max:=q^.val;
                         q:=q^.next;
                    end;
                 {inserimento dell'elemento max ( che è il più grande via via tra gli n,n-1,..,1
                 elementi di p ) in testa alla lista ordinata così in senso crescente}
                 lista^.val:=max;
                 {aggionamento dell'elemento lista}
                 lista:=lista^.next;
                 {aggiornamento di p}
                 p:=p^.next;
            end;
    end;{fine procedura OrdinamentoLista}
    {corpo del programma}
    begin
         repeat
               writeln('--------------------------- Dati di ingresso --------------------------------');
               writeln;
               writeln;
               write('Fornire la dimensione della lista: ');
               readln(n);
               if n>20
               then begin
                         writeln(chr(bell),'Errore nei dati di ingresso! - STOP -');
                         exit;
                    end
               else begin
                         writeln;
                         writeln;
                         writeln('Fornire la lista in ingresso:');
                         writeln;
                         writeln;
                         p:=LeggiLista(n);
                         writeln;
                         writeln;
                         OrdinamentoLista(p,lista);
                         writeln;
                         writeln;
                         while(lista<>nil)
                         do begin
                                 write(lista^.val:3,' ');
                                 lista:=lista^.next;
                            end;
                    end;
                    writeln;
                    writeln('Finito?');
                    writeln;
                    writeln;
                    writeln('Scrivere 1 per terminare 2 per continuare');
                    writeln;
                    writeln;
                    readln(risposta);
         until(risposta=1);
         readln;
     
    end.



Sarò grato da ora a chiunque sia in grado di fornirmi la versione corretta della procedura OrdinamentoLista. Ciao a tutti!!!:)
aaa
01/08/12 9:42
gigisoft
Allora, un piccolo chiarimento,

tu che vuoi fare?
Ordinare la lista che hai?
Oppure creare una copia ordinata della lista, lasciando l'originale inalterata (e quindi disordinata)?

perche' nel primo caso, non ha senso che nella OrdinamentoLista tu ne crei un'altra;

nel secondo caso invece l'approccio che usi e' sbagliato, per esempio, su quali basi come prima istruzione fai questa assegnazione?

lista^.val:=p^.val;


e poi alla prima iterazione del ciclo l'assegnazione

p^.val:=max;


dove vai a modificare il primo elemento della lista originale (p) con un valore (max) che ancora non e' stato definito

ti do un suggerimento funzionale (cioe' ti dico a parole i passi da eseguire, poi pero' devi essere tu a tradurlo in codice)

Caso 1: Ordinamento della lista originale

Passo 1: dichiari tre variabili di tipo punt per scorrere la lista (chiamiamole per esempio Idx, Min, e RelStart);

Passo2: assegni a RelStart il puntatore al primo elemento;

Passo 3: Inizio ciclo esterno, con condizione di uscita quando RelStart^.Next punta a Nil;

Passo 4: Ciclo interno in cui, col puntatore Idx scorri la lista alla ricerca dell'elemento col valore minimo, all'uscita del ciclo memorizzerai in Min il puntatore all'elemento col valore minimo;

Passo 5: uscito dal ciclo interno, scambi i valori degli elementi puntati da Min e da RelStart;

Passo 6: fai puntare RelStart all'elemento successivo;

Passo 7: Fine ciclo esterno, ritorna al passo 3, se non si verifica la condizione di uscita;

-----------------------------------------------------------------------

Caso 2: Creazione di una copia ordinata della lista

Passo 1: dichiari una variabile di tipo punt per scorrere la lista originale (chiamiamola per esempio Idx)
piu' altre due, sempre di tipo punt, per scorrere la nuova lista (chiamiamole per esempio IdxCopy e PrecIdxCopy);

Passo 2: inserisci nella nuova lista un elemento che avra' il valore del primo elemento della lista originale, inoltre fai puntare Idx all'elemento successivo al primo della lista originale;

Passo 3: Inizio ciclo esterno, con condizione di uscita quando Idx punta a Nil;

Passo 4: fai puntare IdxCopy al primo elemento della nuova lista;

Passo 5: Inizio ciclo interno, con condizione di uscita quando Il valore dell'elemento puntato da IdxCopy e' maggiore dell'elemento puntato da Idx;

Passo 6: finche' resti nel ciclo, ad ogni iterazione, fai puntare PrecIdxCopy all'elemento puntato da IdxCopy e poi fai puntare IdxCopy all'elemento successivo;

Passo 7: uscito dal ciclo interno, dovrai inserire un nuovo elemento (per esempio NewEl) nella nuova lista, che dovra' essere posizionato tra PrecIdxCopy e IdxCopy ( in pratica PrecIdxCopy^.Next dovra' puntare a NewEl, e NewEl^.Next dovra' puntare a IdxCopy)

Passo 8: fai puntare Idx all'elemento successivo;

Passo 9: Fine ciclo esterno, ritorna al passo 3, se non si verifica la condizione di uscita;

-----------------------------------------------------------------------

Tutto chiaro? Buon lavoro.

PS Ovviamente, se non ti scrivo il codice (per il quale avrei, tra l'altro, impiegato meno tempo), non e' per cattiveria, ma solo perche' soltanto facendolo tu da solo puoi sperare di imparare qualcosa di programmazione
aaa