Informatica 3: Novità

Quest'area è dedicata agli aggiornamenti relativi al corso di Informatica 3.

Liste, pile e code

Nella lezione del 27/10, abbiamo visto le principali strutture dati basate sul concetto di sequenza:

In aggiunta a quanto detto, ecco i file python con le implementazioni (corrette ed espanse) delle strutture dati viste a lezione. Inoltre la versione C++ delle liste (sia linkate che basate su array) si trova sulla pagina del libro di testo. Potete inoltre trovare qui un'implementazione delle liste tramite doppio puntatore.

Sequences

Today, we introduced the sequence data structures:

Here you can find the files with the python implementation of the data structures. A C++ version can be found on the web page of Shaffer's book. A C implementation of doubly linked lists can be found here.

Simple List Implementation

#!/usr/bin/python
 
class ListItem(object):
        '''Elemento della lista'''
        def __init__(self, elem, next=None):
                self.data=elem
                self._next=next
 
class List(object):
        '''ADT Lista'''
        def __init__(self):
                self.head=ListItem(None)        # testa della lista (elemento dummy)
                self.tail=self.head                             # coda della lista
                self.current=self.head    # posizione corrente (coda della partizione sinistra)
                self.lsize=0                    # dimensione della partizione sinistra
                self.rsize=0                    # dimensione della partizione destra
 
        def setStart(self):
                '''Spostamento di current nella posizione di testa'''
                self.current=self.head
                self.rsize+=self.lsize
                self.lsize=0
 
        def setEnd(self):
                '''Spostamento di current nella posizione di coda'''
                self.current=self.tail
                self.lsize+=self.rsize
                self.rsize=0
 
        def getValue():
                if self.rsize==0 : return None
                else : return self.current._next.data
 
        def insert(self,elem):
                '''Inserimento di un elemento nella testa della partizione destra'''
                self.current._next=ListItem(elem,self.current._next)
                # aggiorna tail se self.current==self.tail
                if self.tail==self.current : self.tail=self.tail._next
                self.rsize+=1
 
        def delete(self):
                '''Cancellazione di un elemento alla testa della partizione destra'''
                if not self.current._next : return None
                res = self.current._next.data
                self.current._next=self.current._next._next
                self.rsize-=1
                return res
 
        def next(self):
                '''Spostamento di current nella posizione successiva'''
                if self.current != self.tail :
                        self.current=self.current._next
                        self.rsize-=1
                        self.lsize+=1
 
        def prev(self):
                '''Spostamento di current nella posizione precedente'''
                if self.current!=self.head:
                        curr=self.head
                        while curr._next != self.current : curr=curr._next
                        self.current=curr
                        self.lsize-=1
                        self.rsize+=1
 
        def setPos(self,pos):
                '''Spostamento di current alla posizione pos; self.lsize=pos'''
                if pos<0 or pos>self.rsize+self.lsize : raise IndexError
                self.rsize = self.rsize+self.lsize-pos
                self.lsize = pos
                self.current=self.head
                for i in range(pos):
                        self.next()
 
        def __str__(self):
                '''Costruzione della versione stampabile della lista'''
                res='['
                if self.head==None : return res+' ]'
                if self.head==self.current : res+=' |'
                curr=self.head._next
                while curr != None :
                        res+=' '+`curr.data`
                        if curr==self.current : res+=' |'
                        curr=curr._next
                return res+' ]'
 
 
# Test -- non viene eseguito quando il modulo viene caricato come libreria
if __name__ == '__main__' :
        def doprint(command) :
                '''Funzione di aiuto per la stampa formattata; notate l'uso di eval per eseguire codice contenuto in una stringa passata come parametro!'''
                eval(command)
                print command, ' '*(20-len(command))+'=>\t', a
 
        a = List()
        doprint('a.insert(1)')
        doprint('a.insert("pippo")')
        doprint('a.insert(2.0)')
        doprint('a.next()')
        doprint('a.insert("pluto")')
        doprint('a.setEnd()')
        doprint('a.delete()')
        doprint('a.prev()')
        doprint('a.insert("2")')
        doprint('a.setStart()')
        doprint('a.delete()')
· 2007/10/31 10:51 · Giovanni Agosta

Notazioni O, Ω e Θ

Nella lezione del 29/10 abbiamo concluso la discussione della complessità computazionale, introducendo tre notazioni che caratterizzano le classi di complessità: le notazioni O, Ω e Θ.

Data una funzione a valori non negativi f(n), valgono le seguenti proprietà:

  • ∃ c, n0 : f(n) ≤ cg(n), ∀ n > n0 ⇒ f(n) ∈ O(g(n))
  • ∃ c, n0 : f(n) ≥ cg(n), ∀ n > n0 ⇒ f(n) ∈ Ω(g(n))
  • f(n) ∈ O(g(n)) ∧ f(n) ∈ Ω(g(n)) ⇒ f(n) ∈ Θ(g(n))

O e Ω stabiliscono dei limiti superiore e inferiore per la complessità di un dato algoritmo. Si noti che questi limiti riguardano la crescita asintotica del costo computazionale al crescere della dimensione dei dati, e non invece i casi medio, ottimo e pessimo, che si determinano a parità di dimensione dei dati.

· 2007/10/29 16:12 · Giovanni Agosta

Complessità computazionale

Nella lezione del 5/11 abbiamo introdotto il concetto di complessità computazionale. La complessità è relativa ad un algoritmo, espresso come sequenza di passi concreti (ovvero applicazioni elementari di strumenti noti). La complessità temporale dell'algoritmo è data dal numero di passi concreti necessari, in funzione della dimensione degli input: C(n).

Per confrontare tra loro due algoritmi che risolvono lo stesso problema (i.e., calcolano la stessa funzione matematica), usiamo l'analisi asintotica della complessità, che rispetto al benchmarking ha il vantaggio di rimanere valida al variare dell'input set.

Ricordiamo che, in una analisi asintotica C(n) è dominata dal termine che cresce più rapidamente. Distinguiamo tre casi particolarmente importanti:

  • 2n
  • na, con a costante
  • log n

Asintoticamente, un termine del tipo 2n ha, indipendentemente dalle costanti, sempre una crescita più veloce di qualunque polinomio in n, e a sua volta un polinomio in n cresce più velocemente di un logaritmo.

Notazioni O, Ω e Θ

Abbiamo inoltre introdotto tre notazioni che caratterizzano le classi di complessità: le notazioni O, Ω e Θ.

Data una funzione a valori non negativi f(n), valgono le seguenti proprietà:

  • ∃ c, n0 : f(n) ≤ cg(n), ∀ n > n0 ⇒ f(n) ∈ O(g(n))
  • ∃ c, n0 : f(n) ≥ cg(n), ∀ n > n0 ⇒ f(n) ∈ Ω(g(n))
  • f(n) ∈ O(g(n)) ∧ f(n) ∈ Ω(g(n)) ⇒ f(n) ∈ Θ(g(n))

O e Ω stabiliscono dei limiti superiore e inferiore per la complessità di un dato algoritmo. Si noti che questi limiti riguardano la crescita asintotica del costo computazionale al crescere della dimensione dei dati, e non invece i casi medio, ottimo e pessimo, che si determinano a parità di dimensione dei dati.

Note

Una imprecisione mia in un esempio svolto oggi a lezione: nel caso f(n) = n + log n , f(n) ∈ Θ(n). Nel caso f(n) = n - log n , dobbiamo dimostrare che n - log n ≥ cn. Lavorando sulla forma generalizzata:

  • a n - b log n ≥ c n

abbiamo

  • (a - c) n ≥ b log n

per a > c, questo e' vero per valori grandi di n.

Python

Nella lezione dell'8/10 abbiamo introdotto il linguaggio di programmazione Python.

Abbiamo in particolare considerato questi aspetti:

  • Strutture dati:
    • Variabili (tipizzazione dinamica forte)
    • Sequenze: liste, dizionari, stringhe e tuple
    • Classi e oggetti (inizializzazione, definizione di metodi)
  • Controllo:
    • Cicli a contatore e su liste (for, while)
    • Condizionali
    • Funzioni, e funzioni anonime (lambda)
    • Eccezioni

Documentazione (sul sito della Python Software Foundation):

Inoltre, esiste un ottimo testo introduttivo a Python (e “free”), Dive into Python (abbiamo visto gli argomenti trattati nei primi 6 capitoli).

The Python Programming Language

In this lecture, we have introduced the Python programming language.

We have considered the following items:

  • Data structures:
    • Variables (dynamic, strong typing; duck typing)
    • Sequences: lists, dictionaries, tuples and strings
    • Classes and objects: initialization, methods, special methods
  • Control flow:
    • Counter and list-based loops (for, while)
    • Conditionals
    • Functions and anonymous functions (lambda)
    • Exceptions
  • Printing facilities

Documentation (one the Python Software Foundation website):

Moreover, there is a good introductory free book on Python, Dive into Python (you should study the first 6 chapters).

See the main course website and the Python website for more Python resources.

· 2007/10/17 11:39 · Giovanni Agosta

Programmazione orientata agli oggetti

Nella lezione del 15/10 abbiamo affrontato il tema della programmazione orientata agli oggetti. In particolare, abbiamo trattato i temi dell'ereditarietà, del polimorfismo, dell'overriding ed overloading dei metodi. Per finire, abbiamo visto il problema dell'ereditarietà multipla e le relative soluzioni (in Perl, Python, Java e C++).

teaching/info3/blog.txt · Last modified: 2007/09/13 16:50 by agosta
Recent changes RSS feed Creative Commons License Donate Driven by DokuWiki