Διαδρομές
/
Python
Python
/
Ασκήσεις
/
Απλή συνδεδεμένη λίστα
Απλή συνδεδεμένη λίστα

Απλή συνδεδεμένη λίστα

Εύκολο

Εισαγωγή

Εργάζεσαι σε μια εταιρεία streaming μουσικής.

Σου έχει ανατεθεί να δημιουργήσεις μια δυνατότητα λίστας αναπαραγωγής για την εφαρμογή αναπαραγωγής μουσικής σου.

Οδηγίες

Γράψε ένα πρωτότυπο της εφαρμογής αναπαραγωγής μουσικής.

Για το πρωτότυπο, κάθε τραγούδι θα αναπαρίσταται απλά από έναν αριθμό. Δεδομένου ενός εύρους αριθμών (των αναγνωριστικών των τραγουδιών), δημιούργησε μια απλά συνδεδεμένη λίστα.

Δεδομένης μιας απλά συνδεδεμένης λίστας, θα πρέπει να μπορείς να αντιστρέψεις τη λίστα για να παίξεις τα τραγούδια με την αντίθετη σειρά.

Note

Η συνδεδεμένη λίστα είναι μια θεμελιώδης δομή δεδομένων στην επιστήμη των υπολογιστών, που χρησιμοποιείται συχνά στην υλοποίηση άλλων δομών δεδομένων.

Το πιο απλό είδος συνδεδεμένης λίστας είναι η απλά συνδεδεμένη λίστα. Αυτό σημαίνει ότι κάθε στοιχείο (ή "κόμβος") περιέχει δεδομένα, μαζί με κάτι που δείχνει στον επόμενο κόμβο της λίστας.

Αν θέλεις να εμβαθύνεις στις συνδεδεμένες λίστες, ρίξε μια ματιά σε αυτό το άρθρο που τις εξηγεί με ωραία σχέδια.

Πώς είναι δομημένη αυτή η άσκηση στην Python

Ενώ οι stacks και οι queues μπορούν να υλοποιηθούν χρησιμοποιώντας lists, collections.deque, queue.LifoQueue και multiprocessing.Queue, αυτή η άσκηση απαιτεί μια "Τελευταίο μέσα, πρώτο έξω" (LIFO) στοίβα που χρησιμοποιεί μια δικής σου κατασκευής απλά συνδεδεμένη λίστα:


Διάγραμμα που αναπαριστά μια στοίβα υλοποιημένη με μια συνδεδεμένη λίστα. Ένας κύκλος με διακεκομμένο περίγραμμα με το όνομα New_Node βρίσκεται στο άκρο αριστερά, με δύο διακεκομμένες γραμμές βέλους να δείχνουν προς τα δεξιά. Το New_Node γράφει "(becomes head) - New_Node - next = node_6". Η πάνω διακεκομμένη γραμμή βέλους έχει την ένδειξη "push" και δείχνει στο Node_6, πάνω και δεξιά. Το Node_6 γράφει "(current) head - Node_6 - next = node_5". Η κάτω διακεκομμένη γραμμή βέλους έχει την ένδειξη "pop" και δείχνει σε ένα κουτί που γράφει "gets removed on pop()". Το Node_6 έχει ένα συμπαγές βέλος που δείχνει προς τα δεξιά στο Node_5, το οποίο γράφει "Node_5 - next = node_4". Το Node_5 έχει ένα συμπαγές βέλος που δείχνει προς τα δεξιά στο Node_4, το οποίο γράφει "Node_4 - next = node_3". Αυτό το μοτίβο συνεχίζεται μέχρι το Node_1, το οποίο γράφει "(current) tail - Node_1 - next = None". Το Node_1 έχει ένα διακεκομμένο βέλος που δείχνει προς τα δεξιά σε έναν κόμβο που λέει "None".


Αυτό δεν πρέπει να το συγχέεις με μια LIFO στοίβα που χρησιμοποιεί δυναμικό πίνακα ή λίστα, η οποία μπορεί να χρησιμοποιεί από κάτω ένα list, queue ή array. Οι stacks που βασίζονται σε δυναμικό πίνακα έχουν διαφορετική θέση του head και διαφορετική πολυπλοκότητα χρόνου (Big-O) και αποτύπωμα μνήμης.


Διάγραμμα που αναπαριστά μια στοίβα υλοποιημένη με πίνακα/δυναμικό πίνακα. Ένα κουτί με διακεκομμένο περίγραμμα με το όνομα New_Node βρίσκεται στο άκρο δεξιά, με δύο διακεκομμένες γραμμές βέλους να δείχνουν προς τα αριστερά. Το New_Node γράφει "(becomes head) -  New_Node". Η πάνω διακεκομμένη γραμμή βέλους έχει την ένδειξη "append" και δείχνει στο Node_6, πάνω και αριστερά. Το Node_6 γράφει "(current) head - Node_6". Η κάτω διακεκομμένη γραμμή βέλους έχει την ένδειξη "pop" και δείχνει σε ένα κουτί με διακεκομμένο περίγραμμα που γράφει "gets removed on pop()". Το Node_6 έχει ένα συμπαγές βέλος που δείχνει προς τα αριστερά στο Node_5. Το Node_5 έχει ένα συμπαγές βέλος που δείχνει προς τα αριστερά στο Node_4. Αυτό το μοτίβο συνεχίζεται μέχρι το Node_1, το οποίο γράφει "(current) tail - Node_1".


Δες αυτές τις δύο ερωτήσεις στο Stack Overflow για μερικά πράγματα που αξίζει να σκεφτείς: Στοίβες και ουρές βασισμένες σε πίνακα έναντι βασισμένες σε λίστα και Διαφορές ανάμεσα σε στοίβα με πίνακα, στοίβα με συνδεδεμένη λίστα και στοίβα. Για περισσότερες λεπτομέρειες σχετικά με τις συνδεδεμένες λίστες, τις στοίβες LIFO και άλλους αφηρημένους τύπους δεδομένων (ADT) στην Python:


Κλάσεις στην Python

Η "κανονική" υλοποίηση μιας συνδεδεμένης λίστας στην Python απαιτεί συνήθως μία ή περισσότερες classes. Για μια καλή εισαγωγή στις classes, δες το classes και τη συνοδευτική άσκηση ellens-alien-game, ή την ενότητα για τις κλάσεις του επίσημου οδηγού της Python.


Ειδικές μέθοδοι στην Python

Τα τεστ αυτής της άσκησης θα καλούν τη len() στο LinkedList σου. Για να δουλέψει η len(), θα χρειαστεί να δημιουργήσεις μια ειδική μέθοδο __len__. Για λεπτομέρειες σχετικά με την υλοποίηση ειδικών μεθόδων ή μεθόδων "dunder" στην Python, δες Python Docs: Προσαρμογή βασικών αντικειμένων και Python Docs: object.len(self).


Κατασκευή ενός επαναλήπτη

Για να μπορείς να διατρέχεις ή να αντιστρέφεις το LinkedList σου, θα χρειαστεί να υλοποιήσεις την ειδική μέθοδο __iter__. Δες την υλοποίηση ενός επαναλήπτη για μια κλάση για λεπτομέρειες υλοποίησης.


Προσαρμογή και πέταγμα εξαιρέσεων

Μερικές φορές είναι απαραίτητο και να προσαρμόσεις και να raise εξαιρέσεις στον κώδικά σου. Όταν το κάνεις αυτό, θα πρέπει πάντα να συμπεριλαμβάνεις ένα κατατοπιστικό μήνυμα σφάλματος που να δείχνει ποια είναι η πηγή του σφάλματος. Αυτό κάνει τον κώδικά σου πιο ευανάγνωστο και βοηθάει σημαντικά στο debugging.

Οι προσαρμοσμένες εξαιρέσεις μπορούν να δημιουργηθούν μέσω νέων κλάσεων εξαιρέσεων (δες τις classes για περισσότερες λεπτομέρειες) που συνήθως είναι υποκλάσεις της Exception.

Σε περιπτώσεις όπου ξέρεις ότι η πηγή του σφάλματος θα είναι παράγωγο ενός συγκεκριμένου τύπου εξαίρεσης, μπορείς να επιλέξεις να κληρονομήσεις από έναν από τους built in error types κάτω από την κλάση Exception. Όταν πετάς το σφάλμα, θα πρέπει και πάλι να συμπεριλαμβάνεις ένα κατατοπιστικό μήνυμα.

Αυτή η συγκεκριμένη άσκηση απαιτεί να δημιουργήσεις μια προσαρμοσμένη εξαίρεση που να πετιέται/"ρίχνεται" όταν η συνδεδεμένη λίστα σου είναι άδεια. Τα τεστ θα περάσουν μόνο αν προσαρμόσεις τις κατάλληλες εξαιρέσεις, τις πετάξεις με raise και συμπεριλάβεις τα κατάλληλα μηνύματα σφάλματος.

Για να προσαρμόσεις μια γενική εξαίρεση, δημιούργησε μια class που κληρονομεί από την Exception. Όταν πετάς την προσαρμοσμένη εξαίρεση με ένα μήνυμα, γράψε το μήνυμα ως όρισμα στον τύπο 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.")
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Python Exercism

Έτοιμος να ξεκινήσεις την άσκηση Απλή συνδεδεμένη λίστα;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Python με 17 έννοιες146 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.