Lezione del 9 Febbraio 2001 & Esercizi proposti (a fondo pagina!)

Altri esempi di procedure e funzioni che lavorano su liste concatenate (ulteriori commenti verranno aggiunti al piu' presto)


procedure delete_el_it(var l:list; e:elemtype);

{AF: elimina la prima occorrenza di 'e' in 'l', vers. iterativa}

 var p,t:list;
     trov:boolean;

 begin
  trov:=false;
  t:=l; p:=l; {t e` per non perdere la testa della lista, p servira`
	       per puntare all'el. prec. a quello puntato da t}
  while (t<>nil) and (not trov) do
   begin
    if t^.elem=e
    then
     begin
      trov:=true;
      if p=t then l:=l^.next
                      {nel caso primo el. devo mod. 'l'}
      else p^.next:=t^.next;
     end;
     p:=t;
     t:=t^.next;
    end
 end;


procedure delete_el_ric(var l:list; p:list; e:elemtype);

{AF: elimina la prima occorrenza di 'e' in 'l', vers. ricorsiva}

 begin
  if l<>nil
  then begin
   if l^.elem=e then
    if p=l then l:=l^.next
    else p^.next:=l^.next
   else delete_el_ric(l^.next, l, e)
  end
 end;
La 'delete_el_ric' ha un parametro in piu' rispetto alla 'delete_el_it', il parametro 'p'. Esso ha la stessa funzione della variabile locale 'p' della versione iterativa, ovvero quella di puntare all'elemento precedente all'elemento puntato da 'l' (puntato da 't' nella versione iterativa). Dal main, se per esempio 'lis' e`una lista dalla quale vogliamo cancellare '5', chiameremo la 'delete_el_ric' con: delete_el_ric(lis,lis,5).
function length(l:list):integer;

{AF: restituisce il numero degli elementi di 'l'}

 begin
  if l=nil then length:=0
  else length:=1+length(l^.next)
 end;


procedure delete(var l:list; i:integer);

{AF: cancella l'elemento di posizione i-esima in 'l'}

 var p,t:list;
     cont:integer;

 begin
  if (0>=i) OR (i>length(l)) then writeln('errore...')
  else
   begin
    if i=1 then l:=l^.next
    else
     begin
      t:=l^.next; p:=l;
         {t e` per non perdere la testa della lista, p 
          punta all'el. prec. a quello puntato da t}
      cont:=2;
      while i>cont do begin cont:=cont+1; p:=t; t:=t^.next end;
      p^.next:=t^.next;
     end
   end
 end;


procedure search(l:list; i:integer; var e:elemtype);

{AF: restituisce in 'e' l'elemento i-esimo}

{Fatta come funzione sarebbe piu' elegante, ma piu' difficile segnalare
 la condizione di errore}

 var pos:integer;

 begin
   if (0>=i) OR (i>length(l)) then writeln('errore...')
   else
    begin
     for pos:=1 to i-1 do
      l:=l^.next;
     e:=l^.elem
    end
 end;
Notate l'uso del parametro 'e': e` proprio in 'e' che mettiamo il risultato della nostra ricerca, ovvero l''elem' i-esimo.


Esercizi proposti

- Preparate una UNIT 'Liste' contenente: readlist, writelist, cons, copy, equal (viste con Giovannetti), search, delete, insert (NON ANCORA FATTA).

- Provate a proporre una soluzione alternativa alla 'delete_el_it' che sia piu' elegante/semplice/efficiente/etc.

- Scrivete una procedura che sia una modifica della 'delete_el_it' (e/o della 'delete_el_ric') che cancelli TUTTE le occorenze di 'e' in 'l'.

- Modificate la 'cerca_el' presentata nella lezione del 2/2/2001 e riproposta qui sotto, in modo che restituisca la posizione dell'elemento 'e' in 'l', se 'e' appartiene a 'l', invece di un booleano.

function cerca_el(l:list; e:elemtype):bool;

{AF:  restituisce TRUE se l'elemento 'e' appartiene alla lista 'l',
 FALSE altrimenti}

begin
 if (l=nil) then cerca_el:=false 
 else if (l^.elem=e) then cerca_el:=true 
      else cerca_el:=cerca_el(l^.next, e);
end;

- Data una lista di interi e una di booleani della stessa lunghezza, modificare la prima nel seguente modo: se nell'elemento di posizione 'i' nella lista di booleani c'e` TRUE, cancellare il corrispondente i-esimo elemento nella lista degli interi. ESEMPIO: L1 = 1,2,3,4, L2 = T,F,F,T ==> L1 diventa L1 = 2,3.

- Scrivete una procedura che, date due liste L1 e L2 di interi, produca una terza lista L3 che contenga come elementi la somma degli elementi di posizione corrispondente nelle liste in input. Se una delle due liste in input e` piu' lunga, gli elementi in sovrappiu' andranno copiati cosi' come sono nella lista ouput L3. ESEMPIO: L1 = 1,2, L2 = 3,4,5 ==> L3 = 4,6,5.


Soluzioni (Non ancora presenti)