Track
/
Python
Python
/
Esercizi
/
Lista concatenata semplice
Lista concatenata semplice

Lista concatenata semplice

Facile

Introduzione

Lavori per un'azienda di streaming musicale.

Il tuo compito è creare una funzionalità playlist per l'applicazione di riproduzione musicale.

Istruzioni

Scrivi un prototipo dell'applicazione del lettore musicale.

Per il prototipo, ogni brano sarà semplicemente rappresentato da un numero. Dato un intervallo di numeri (gli ID dei brani), crea una lista concatenata semplice.

Data una lista concatenata semplice, dovresti poter invertire la lista per riprodurre i brani in ordine inverso.

Note

La lista concatenata è una struttura dati fondamentale dell'informatica, spesso usata per implementare altre strutture dati.

La versione più elementare è la lista concatenata semplice. Questo significa che ogni elemento (o «nodo») contiene dei dati, insieme a qualcosa che punta al nodo successivo della lista.

Se vuoi approfondire le liste concatenate, dai un'occhiata a questo articolo che lo spiega con dei bei disegni.

Come è strutturato questo esercizio in Python

Mentre stacks e queues possono essere implementati usando lists, collections.deque, queue.LifoQueue e multiprocessing.Queue, questo esercizio richiede uno stack «Last in, First Out» (LIFO) che usa una lista concatenata singola fatta su misura:


Diagramma che rappresenta uno stack implementato con una lista concatenata. Un cerchio con il bordo tratteggiato, chiamato New_Node, si trova all'estrema sinistra, con due linee tratteggiate a freccia rivolte verso destra. New_Node dice "(becomes head) - New_Node - next = node_6". La linea tratteggiata superiore è etichettata "push" e punta a Node_6, in alto a destra. Node_6 dice "(current) head - Node_6 - next = node_5". La linea tratteggiata inferiore è etichettata "pop" e punta a un riquadro che dice "gets removed on pop()". Node_6 ha una freccia continua che punta verso destra a Node_5, che dice "Node_5 - next = node_4". Node_5 ha una freccia continua che punta verso destra a Node_4, che dice "Node_4 - next = node_3". Questo schema prosegue fino a Node_1, che dice "(current) tail - Node_1 - next = None". Node_1 ha una freccia tratteggiata che punta verso destra a un nodo che dice "None".


Non va confuso con uno stack LIFO che usa un array dinamico o una lista, che sotto può usare una list, una queue o un array. Gli stacks basati su array dinamici hanno una posizione di head diversa, una diversa complessità temporale (Big-O) e un diverso consumo di memoria.


Diagramma che rappresenta uno stack implementato con un array/array dinamico. Un riquadro con il bordo tratteggiato, chiamato New_Node, si trova all'estrema destra, con due linee tratteggiate a freccia rivolte verso sinistra. New_Node dice "(becomes head) - New_Node". La linea tratteggiata superiore è etichettata "append" e punta a Node_6, in alto a sinistra. Node_6 dice "(current) head - Node_6". La linea tratteggiata inferiore è etichettata "pop" e punta a un riquadro con il contorno tratteggiato che dice "gets removed on pop()". Node_6 ha una freccia continua che punta verso sinistra a Node_5. Node_5 ha una freccia continua che punta verso sinistra a Node_4. Questo schema prosegue fino a Node_1, che dice "(current) tail - Node_1".


Dai un'occhiata a queste due domande su Stack Overflow per alcune considerazioni: Array-Based vs List-Based Stacks and Queues e Differences between Array Stack, Linked Stack, and Stack. Per maggiori dettagli sulle liste concatenate, sugli stack LIFO e su altri tipi di dati astratti (ADT) in Python:


Le classi in Python

L'implementazione «canonica» di una lista concatenata in Python di solito richiede una o più classes. Per una buona introduzione alle classes, vedi classes e l'esercizio abbinato ellens-alien-game, oppure Class section of the Official Python Tutorial.


I metodi speciali in Python

I test di questo esercizio chiameranno len() sulla LinkedList. Perché len() funzioni, dovrai creare un metodo speciale __len__. Per i dettagli su come implementare i metodi speciali o "dunder" in Python, vedi Python Docs: Basic Object Customization e Python Docs: object.len(self).


Costruire un iteratore

Per poter scorrere o invertire la LinkedList, dovrai implementare il metodo speciale __iter__. Vedi implementing an iterator for a class per i dettagli di implementazione.


Personalizzare e sollevare eccezioni

A volte è necessario sia personalizzare sia raise le eccezioni nel codice. Quando lo fai, includi sempre un messaggio di errore significativo che indichi qual è l'origine dell'errore. Questo rende il codice più leggibile e aiuta molto nel debug.

Le eccezioni personalizzate si possono creare tramite nuove classi di eccezione (vedi classes per maggiori dettagli) che sono in genere sottoclassi di Exception.

Nei casi in cui sai che l'origine dell'errore sarà una derivazione di un certo tipo di eccezione, puoi scegliere di ereditare da uno dei built in error types sotto la classe Exception. Quando sollevi l'errore, includi comunque un messaggio significativo.

Questo particolare esercizio richiede di creare un'eccezione personalizzata da sollevare/«lanciare» quando la lista concatenata è vuota. I test passeranno solo se personalizzi le eccezioni appropriate, raise quelle eccezioni e includi messaggi di errore appropriati.

Per personalizzare un'eccezione generica, crea una class che eredita da Exception. Quando sollevi l'eccezione personalizzata con un messaggio, scrivi il messaggio come argomento del tipo exception:

# subclassing Exception to create EmptyListException
class EmptyListException(Exception):
    """Exception raised when the linked list is empty.

    message: explanation of the error.

    """
    def __init__(self, message):
        self.message = message

# raising an EmptyListException
raise EmptyListException("The list is empty.")
Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Python Exercism

Vuoi iniziare Lista concatenata semplice?

Iscriviti a Exercism per imparare e padroneggiare Python con 17 concetti146 esercizi e il mentoring di persone reali, tutto gratis.