Δομές Δεδομένων & Αλγόριθμοι

Σχετικά έγγραφα
Φροντιστήριο 4 Σκελετοί Λύσεων

Φροντιστήριο 4 Σκελετοί Λύσεων

Κατ οίκον Εργασία 2 Σκελετοί Λύσεων

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

Διάλεξη 12: Λίστες Υλοποίηση & Εφαρμογές. Διδάσκων: Παναγιώτης Ανδρέου

ΠΛΗ111. Ανοιξη Μάθηµα 3 ο. Συνδεδεµένες Λίστες. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

Λίστες και Ακολουθίες. Λίστες και ακολουθίες 1

Υλοποίηση Λιστών. Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα:

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ. Δομές Δεδομένων. Ιωάννης Γ. Τόλλης Τμήμα Επιστήμης Υπολογιστών Πανεπιστήμιο Κρήτης

Εργαστήριο 4: Υλοποίηση Αφηρημένου Τύπου Δεδομένων: Ταξινομημένη Λίστα

Διάλεξη 07: Λίστες Ι Υλοποίηση & Εφαρμογές

Στοίβες με Δυναμική Δέσμευση Μνήμης

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ

Δομές Δεδομένων (Data Structures)

Δομές Δεδομένων & Αλγόριθμοι

Βασικές οµές εδοµένων

Διάλεξη 08: Λίστες ΙΙ Κυκλικές Λίστες

Διάλεξη 16: Σωροί. Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Ουρές Προτεραιότητας - Ο ΑΤΔ Σωρός, Υλοποίηση και πράξεις

Βασικές Δομές Δεδομένων

Διάλεξη 26: Σωροί. Διδάσκων: Παναγιώτης Ανδρέου

Διάλεξη 08: Λίστες ΙΙ Κυκλικές Λίστες

Διάλεξη 21η: Απλά Συνδεδεμένες Λίστες

Δομές δεδομένων (2) Αλγόριθμοι

υναµική έσµευση Μνήµης (συν.) ΕΠΛ 132 Αρχές Προγραµµατισµού ΙΙ 2 Εφαρµογή

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

Δομές Δεδομένων. Καθηγήτρια Μαρία Σατρατζέμη. Τμήμα Εφαρμοσμένης Πληροφορικής. Δομές Δεδομένων. Τμήμα Εφαρμοσμένης Πληροφορικής

4. Συνδεδεμένες Λίστες

Στοίβες - Ουρές. Στοίβα (stack) Γιάννης Θεοδωρίδης, Νίκος Πελέκης, Άγγελος Πικράκης Τµήµα Πληροφορικής

υναµικές οµές εδοµένων

Δομές Δεδομένων (Data Structures)

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. ΕΠΛ 035: οµές εδοµένων και Αλγόριθµοι για Ηλεκτρολόγους Μηχανικούς και Μηχανικούς Υπολογιστών

Ιδιοκτησία Αντικειµένου

Κατ οίκον Εργασία 2 Σκελετοί Λύσεων

Δομές Δεδομένων. Ενότητα 4: Ο ΑΤΔ Λίστα & Υλοποίηση Λίστας με σειριακή αποθήκευση- Ο ΑΤΔ Συνδεδεμένη Λίστα- Υλοποίηση ΑΤΔ Συνδεδεμένη Λίστα με πίνακα

Διάλεξη 11: Φροντιστήριο για Στοίβες. Διδάσκων: Παναγιώτης Ανδρέου. ΕΠΛ035 Δομές Δεδομένων και Αλγόριθμοι για Ηλ. Μηχ. Και Μηχ. Υπολ.

Διάλεξη 05: Αφηρημένοι Τύποι Δεδομένων

Κατ οίκον Εργασία 2 Σκελετοί Λύσεων

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δυναμική Δέσμευση Μνήμης και Δομές Δεδομένων (Φροντιστήριο)

ΕΠΛ231 Δομές Δεδομένων και Αλγόριθμοι 5. Αφηρημένοι Τύποι Δεδομένων / Στοίβες και Ουρές

Βασικές Έννοιες Δοµών Δεδοµένων

Τύποι Δεδομένων και Απλές Δομές Δεδομένων. Παύλος Εφραιμίδης V1.0 ( )

Σύνοψη Προηγούμενου. Λίστες (Lists) Συνδεδεμένες Λίστες: Εισαγωγή (1/2) Συνδεδεμένες Λίστες. Ορέστης Τελέλης

Διάλεξη 16: Σωροί. Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Ουρές Προτεραιότητας - Ο ΑΤΔ Σωρός, Υλοποίηση και πράξεις

Διάλεξη 13: Δομές Δεδομένων ΙΙ (Ταξινομημένες Λίστες)

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

Προγραµµατισµός Ι (ΗΥ120)

Εργαστήριο 5: Υλοποίηση Αφηρημένου Τύπου Δεδομένων: Διπλά Συνδεδεμένη Λίστα

ιαφάνειες παρουσίασης #5 (β)

Ενότητα 2: Στοίβες Ουρές - Λίστες Ασκήσεις και Λύσεις

Προγραμματισμός Ι. Δομές Δεδομένων. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Διάλεξη 08: ΛίστεςΙΙ Κυκλικές Λίστες. Διδάσκων: Παναγιώτης Ανδρέου

Διάλεξη 22: Δυαδικά Δέντρα. Διδάσκων: Παναγιώτης Ανδρέου

ΠΛΗ111. Ανοιξη Μάθηµα 5 ο. Ουρά. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

Συλλογές, Στοίβες και Ουρές

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. ΘΕΩΡΗΤΙΚΗ ΑΣΚΗΣΗ 2 ΛΥΣΕΙΣ Γραμμικές Δομές Δεδομένων, Ταξινόμηση

υναµικές οµές εδοµένων (συν.) Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα:

Οντοκεντρικός Προγραμματισμός

Θεωρητικό Μέρος. int rec(int n) { int n1, n2; if (n <= 5) then return n; else { n1 = rec(n-5); n2 = rec(n-3); return (n1+n2); } }

Διάλεξη 9: Αφηρημένοι Τύποι Δεδομένων. Διδάσκων: Παναγιώτης Ανδρέου

Διδάσκων: Παναγιώτης Ανδρέου

Alternative to Balanced Trees, Comms of the ACM, 33(6), June 1990,

Διασυνδεδεμένες Δομές. Λίστες. Προγραμματισμός II 1

διεύθυνση πρώτου στοιχείου διεύθυνση i-οστού στοιχείου T t[n]; &t[0] είναι t &t[i] είναι t + i*sizeof(t)

Ενότητες 3 & 4: Δένδρα, Σύνολα & Λεξικά Ασκήσεις και Λύσεις

Απλές Δοµές Δεδοµένων Στην ενότητα αυτή θα γνωρίσουµε ορισµένες απλές Δοµές Δεδοµένων και θα τις χρησιµοποιήσουµε για την αποδοτική επίλυση του προβλή

Στοιχειώδεις Δομές Δεδομένων

Διδάσκων: Παναγιώτης Ανδρέου

Επιλογές και Κριτήρια Σχεδιασμού ΑΤΔ Ανεξαρτήτως από Γλώσσα Υλοποίησης 24/4/2012

Διάλεξη 15: Δομές Δεδομένων IV (Διπλά Συνδεδεμένες Λίστες)

ΠΑΡΑΡΤΗΜΑ: QUIZ ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ

Διδάσκων: Παναγιώτης Ανδρέου

Προγραμματισμός Ι (ΗΥ120)

Διάλεξη 10: Δομές Δεδομένων Ι (Στοίβες & Ουρές)

IsEmptyList(L): επιστρέφει true αν L = < >, false

Πανεπιστήμιο Πειραιώς Σχολή Τεχνολογιών Πληροφορικής και Επικοινωνιών Τμήμα Ψηφιακών Συστημάτων ομές εδομένων

Πανεπιστήμιο Πειραιώς Σχολή Τεχνολογιών Πληροφορικής και Επικοινωνιών Τμήμα Ψηφιακών Συστημάτων ομές εδομένων

Διάλεξη 14: Δομές Δεδομένων ΙΙI (Λίστες και Παραδείγματα)

Αναδροµή. Σε αυτήν την (βοηθητική) ενότητα θα µελετηθούν τα εξής : Η έννοια της αναδροµής Υλοποίηση και αποδοτικότητα Αφαίρεση της αναδροµής

Προγραμματισμός Η/Υ. Ενότητα 9: Ειδικά θέματα Δομών Δεδομένων

Σημειώσεις έκτης και έβδομης εβδομάδας

Κεφάλαιο 10 Ψηφιακά Λεξικά

ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. Δοµές Δεδοµένων

Κατ οίκον Εργασία 3 Σκελετοί Λύσεων

Διάλεξη 15: Δομές Δεδομένων IV (Διπλά Συνδεδεμένες Λίστες)

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ

ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. Δοµές Δεδοµένων

Προγραμματισμός Δομές Δεδομένων

ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΥΠΡΟΥ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. ΑΣΚΗΣΗ 4 Σωροί, Γράφοι

Κεφάλαιο 6 Ουρές Προτεραιότητας

Γραμμικές λίστες. Γκόγκος Χρήστος ΤΕΙ Ηπείρου

Δομές Δεδομένων. Ενότητα 6: Εφαρμογή Συνδεδεμένων Λιστών: Αλφαβητικό ευρετήριο κειμένου- Υλοποίηση ΑΤΔ Στοίβα και Ουρά με δείκτες

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ

lab13grades Άσκηση 2 -Σωστά απελευθερώνετε ολόκληρη τη λίστα και την κεφαλή

Διάλεξη 06: Συνδεδεμένες Λίστες & Εφαρμογές Στοιβών και Ουρών

Διαδικασιακός Προγραμματισμός

Οργάνωση αρχείων: πως είναι τοποθετηµένες οι εγγραφές ενός αρχείου όταν αποθηκεύονται στο δίσκο

Ενότητα 2: Στοίβες Ουρές - Λίστες Ασκήσεις και Λύσεις

Διάλεξη 12: Δέντρα ΙΙ Δυαδικά Δέντρα

ΠΑΝΕΠΙΣΤΗΜΙΟ ΠΑΤΡΩΝ ΠΟΛΥΤΕΧΝΙΚΗ ΣΧΟΛΗ ΤΜΗΜΑ ΜΗΧΑΝΙΚΩΝ ΗΛΕΚΤΡΟΝΙΚΩΝ ΥΠΟΛΟΓΙΣΤΩΝ ΚΑΙ ΠΛΗΡΟΦΟΡΙΚΗΣ

Transcript:

Λίστες Λίστες - Απλά Συνδεδεμένες Λίστες - Διπλά Συνδεδεμένες Λίστες

Είδη Γραμμικών Λιστών Σειριακή Λίστα Καταλαμβάνει συνεχόμενες θέσεις κύριας μνήμης Συνδεδεμένη Λίστα Οι κόμβοι βρίσκονται σε απομακρυσμένες θέσεις, συνδεδεμένες όμως μεταξύ τους με δείκτες Στατικές Λίστες Ο μέγιστος αριθμός στοιχείων είναι εξ αρχής γνωστός (υλοποίηση με σειριακές λίστες) Δυναμικές Λίστες Ο μέγιστος αριθμός στοιχείων δεν είναι γνωστός. Επιτρέπεται η επέκταση ή και συρρίκνωση της λίστας κατά την εκτέλεση του προγράμματος (υλοποίηση με συνδεδεμένες λίστες)

Μονά Διασυνδεδεμένη Λίστα Μία μονά διασυνδεδεμένη λίστα είναι μία συμπαγής δομή δεδομένων που αποτελείται από μία ακολουθία κόμβων Κάθε κόμβος περιέχει στοιχείο σύνδεσμο προς τον επόμενο κόμβο στοιχείο επόμενο κόμβος A B C D

Θέση (Position) ΑΔΤ Τα Position ADT μοντέλα μοντελοποιούν την έννοια της θέσης μέσα σε μια δομή δεδομένων όπου ένα μοναδικό αντικείμενο αποθηκεύεται Η ειδική θέση null αναφέρεται σε απουσία αντικειμένου Οι θέσεις παρέχουν μια ενοποιημένη αναπαράσταση των διαφορετικών τρόπων αποθήκευσης δεδομένων, όπως το κελί ενός πίνακα ο κόμβος μιας διασυνδεδεμένης λίστας Συναρτήσεις: Object& element(): επιστρέφει το στοιχείο που είναι αποθηκευμένο στην θέση αυτή bool isnull(): επιστρέφει αλήθεια αν είναι null θέση

Λίστα ΑΔΤ Το μοντέλο μιας Λίστα ΑΔΤ μοντελοποιεί μια ακολουθία από θέσεις που αποθηκεύουν αυθαίρετα αντικείμενα Εγκαθιστά μία πριν/μετά σχέση μεταξύ των θέσεων Μέθοδοι ερωτήσεων: isfirst(p), islast(p) Μέθοδοι πρόσβασης: first(), last() before(p), after(p) Μέθοδοι ενημέρωσης: replaceelement(p, o), swapelements(p, q) insertbefore(p, o), insertafter(p, o), insertfirst(o), insertlast(o) remove(p)

Γραμμικές Λίστες (linear lists) Μια γραμμική λίστα είναι μια πεπερασμένη, ταξινομημένη ακολουθία δεδομένων Βασική αρχή: Τα στοιχεία της λίστας έχουν μια θέση μέσα στην ακολουθία (1 ο,2 ο,3 ο κοκ.) Συμβολισμός: <e 1, e 2,,e n > Ποιες λειτουργίες πρέπει να υλοποιήσουμε: Δημιουργία μιας γραμμικής λίστας Καθορισμός του αν η λίστα είναι άδεια, καθορισμός του του μήκους της λίστας Εύρεση του k-οστού στοιχείου, διαγραφή του k-οστού στοιχείου, εισαγωγή νέου στοιχείου ακριβώς μετά το k-οστό Αναζήτηση ενός στοιχείου x μέσα στη λίστα

Αρχικοποίηση listptr addr of list count 0 headptr NULL void initializelist(list* listptr) { listptr->headptr = NULL; listptr->count = 0; }

Τοποθέτηση σε Συγκεκριμένη Θέση Έλεγχος αν η θέση (position) είναι μέσα στα όρια. Αρχίζουμε από τον κόμβο head Θέτουμε index =0 while index < position Ακολουθούμε το δείκτη next Αυξάνουμε τη μεταβλητή index Επιστρέφουμε τον κόμβο

Τοποθέτηση σε Συγκεκριμένη Θέση headptr 0 1 2 0x2030 0x30a8 2 position 0 i nodeptr

Τοποθέτηση σε Συγκεκριμένη Θέση headptr 0 1 2 0x2030 0x30a8 2 position 1 i 0x2030 nodeptr

Τοποθέτηση σε Συγκεκριμένη Θέση headptr 0 1 2 0x2030 0x30a8 2 position 2 i 0x30a8 nodeptr

Εισαγωγή headptr Εισαγωγή στη θέση 0. 0 1 2 headptr 0 1 2 3 newnodeptr

Εισαγωγή στη θέση 1. headptr 0 1 2 newnodeptr headptr 0 2 3 newnodeptr 1

Εισαγωγή στη Αρχή headptr 0x2008 0x30a8 0x2000 newnodeptr position 0x2000 0

Εισαγωγή στην Αρχή headptr 0x2008 0x30a8 0x2000 newnodeptr position 0x2000 0

Εισαγωγή στην Αρχή headptr 0x2008 0x30a8 0x2000 newnodeptr position 0x2000 0

Εισαγωγή Ενδιάμεσα headptr 0x3050 prevptr newnodeptr 0x2000 0x2000 position 1

Εισαγωγή Ενδιάμεσα headptr 0x3050 prevptr newnodeptr 0x2000 0x2000 position 1

Εισαγωγή Ενδιάμεσα headptr 0x3050 prevptr newnodeptr 0x2000 0x2000 position 1

Διαγραφή headptr 0 1 Διαγραφή θέσης 0. 2 3 0 1 2 headptr

headptr Διαγραφή θέσης 2. 0 headptr 1 2 3 0 1 2

Διαγραφή 1ου Κόμβου headptr 0x2030 0x30a8 0 position oldnodeptr

Διαγραφή 1ου Κόμβου 0x2030 0x30a8 0 position headptr oldnodeptr

Διαγραφή 1ου Κόμβου 0x2030 0x30a8 0 position headptr oldnodeptr

Διαγραφή Ενδιάμεσου Κόμβου headptr 0x2030 0x30a8 1 position 0x2030 0x2030 prevptr oldnodeptr

Διαγραφή Ενδιάμεσου Κόμβου headptr 0x2030 0x30a8 1 position 0x2030 0x2030 prevptr oldnodeptr

Διαγραφή Ενδιάμεσου Κόμβου headptr 0x30a8 1 position 0x2030 0x2030 prevptr oldnodeptr

Παράδειγμα Ο ΑΤ λίστα ορίζεται ως µια ακολουθία στοιχείων συνοδευόµενη από πράξεις που επιτρέπουν εισαγωγή και εξαγωγή στοιχείων σε οποιαδήποτε θέση της λίστας. Να υλοποιήσετε τις πιο κάτω βασικές πράξεις λίστας: a)access(l, i) επέστρεψε το i-οστό στοιχείο της L b)insert_after(l, x, i) εισήγαγε το x µετά από το i-οστό στοιχείο της L. c)delete(l, i) αφαίρεσε το i-οστό στοιχείο της L Να εξηγήσετε µε σαφήνεια πως µπορούµε να υλοποιήσουµε αυτό τον ΑΤ χρησιµοποιώντας a)(ι) πίνακες και b)(ιι) συνδεδεµένες λίστες. Συγκεκριµένα, να γράψετε µια καθαρή περιγραφή των µεταβλητών που χρειάζονται για τη δοµή και την υλοποίηση των πράξεων σε ψευδοκώδικα. Να υπολογίσετε το χρόνο εκτέλεσης των διαδικασιών και να συγκρίνετε τις δύο υλοποιήσεις.

Ο ζητούµενος ΑΤ µπορεί να υλοποιηθεί ως εξής: ιαδοχική χορήγηση µνήµης (Πίνακας) Υποθέτουµε ότι οι λίστες µας έχουν µέγιστο µέγεθος max και χρησιµοποιούµε τη δοµή typedef struct List{ type elements[max]; int size; } list; Οι διαδικασίες υλοποιούνται ως εξής: type Access (list *L, int i){ if (i< L->size) return L[i-1]; } Χρόνος Εκτέλεσης: O(1) InsertAfter(list *L, int i, type x){ if ( L->size < max AND i < L->size ){ for ( k = L->size; k > i; k++) L->elements[k] = L->elements[k-1]; L->elements[i] = x; L->size++; } Χρόνος Εκτέλεσης: n i O(n), όπου n είναι το µέγεθος της λίστας. Delete(list *L, int i){ if (i < L->size ){ for ( k = i-1; k < L->size; k++) L->elements[k] = L->elements[k+1]; L->size--; } Χρόνος Εκτέλεσης: n i ε O(n), όπου n είναι το µέγεθος της λίστας.

Συνδετική χορήγηση µνήµης Χρησιµοποιούµε τις πιο κάτω δοµές typedef struct Node{ type data; struct node *next; } node; typedef struct List{ node *top; int size; } list; Οι διαδικασίες υλοποιούνται ως εξής: type Access (list *L, int i){ if i> L->size return; p = L->top; for (j=0; j < i; j++) p= p->next; return p->data; } Χρόνος Εκτέλεσης: i, O(n), όπου n είναι το µέγεθος της λίστας. InsertAfter(list *L, int i, type x){ if (i > L->size) return; p = L->top; for (j=0; j < i; j++) p= p->next; q = (node *) malloc (sizeof(node)); q->data = x; q->next = p->next; p->next = q; } Χρόνος Εκτέλεσης: i ε O(n), όπου n είναι το µέγεθος της λίστας. Delete(list *L, int i){ node * ptr; if (i > L->size) return; p = L->top; for (j=0; j < i; j++) p= p->next; ptr = p->next; p->next = p->next->next; free(ptr); } Χρόνος Εκτέλεσης: i εo(n), όπου n είναι το µέγεθος της λίστας.

Σύγκριση Η υλοποίηση του ΑΤ µε διαδοχική χορήγηση µνήµης αποτελείται από απλούστερες προγραµµατιστικά διαδικασίες και από αυτές η Access είναι αποδοτικότερη από την αντίστοιχη διαδικασία της υλοποίησης µε δυναµική δέσµευση µνήµης. Το βασικό πλεονέκτηµα της υλοποίησης µε δυναµική δέσµευση µνήµης είναι ότι δεν επιβάλλει περιορισµούς σχετικά µε το πλήθος των στοιχείων της λίστας, και ανά πάσα στιγµή χρησιµοποιεί µνήµη ανάλογη µε το πλήθος των στοιχείων της λίστας. Αντίθετα η υλοποίηση µε πίνακα δεσµεύει µνήµη για τις max θέσεις του πίνακα καθ όλη τη διάρκεια της εκτέλεσης του προγράµµατος, άσχετα µε το πλήθος των στοιχείων της λίστας. Παρατηρούµε όµως, πως στην υλοποίηση µε δυναµική δέσµευση µνήµης χρειάζεται να αποθηκεύουµε και µνήµη για του δείκτες next κάθε κόµβου της λίστας.

Γραμμική Λίστα με Πίνακα class LinearList { public: LinearList(int MaxListSize = 10); // constructor ~LinearList() {delete [] element;} // destructor bool IsEmpty() const {return length == 0;} int Length() const {return length;} bool Find(int k, T& x) const; // return the k'th element of list in x int Search(const T& x) const; // return position of x LinearList<T>& Delete(int k, T& x); // delete k'th element and return in x LinearList<T>& Insert(int k, const T& x); // insert x just after k'th element void Output(ostream& out) const; private: int length; int MaxSize; T *element; // dynamic 1D array };

Γραμμική Συνδεδεμένη Λίστα class Chain { public: Chain() {first = 0;} ~Chain(); bool IsEmpty() const {return first == 0;} int Length() const; class ChainNode { T data; ChainNode<T> *link; }; bool Find(int k, T& x) const; int Search(const T& x) const; Chain<T>& Delete(int k, T& x); Chain<T>& Insert(int k, const T& x); void Output(ostream& out) const; private: ChainNode<T> *first; // pointer to first node };

Διπλά Διασυνδεδεμένη Λίστα Μία διπλά διασυνδεδεμένη λίστα παρέχει μια φυσική υλοποίηση της Λίστας ΑΔΤ Οι κόμβοι υλοποιούν την θέση και περιέχουν: στοιχείο σύνδεσμο στον προηγούμενο κόμβο σύνδεσμο στον επόμενο κόμβο Ειδικοί κόμβοι header και trailer header prev elem κόμβοι/θέσεις next κόμβος trailer στοιχεία

Διπλά Συνδεδεμένη Λίστα Επίσης γραμμικές διατάξεις Δυο σύνδεσμοι σε κάθε κόμβο, προς τον επόμενο και προς τον προηγούμενο Γενική μορφή, π.χ. για υλοποίηση ουράς: first last

Διπλά Συνδεδεμένη Λίστα Πήγαινε σε συγκεκριμένη θέση Εισαγωγή σε συγκεκριμένη θέση Διαγραφή από συγκεκριμένη θέση Ανάγνωση δεδομένων συγκεκριμένης θέσης Αντικατάσταση Διάσχιση λίστας και στις δύο κατευθύνσεις.

Διπλά Συνδεδεμένη Λίστα 0 1 2 3 4 currentptr

struct DoubleLinkNodeRec { float value; struct DoubleLinkNodeRec* nextptr; struct DoubleLinkNodeRec* previousptr; }; typedef struct DoubleLinkNodeRec Node; struct DoubleLinkListRec { int count; Node* currentptr; int position; }; typedef struct DoubleLinkListRec DoubleLinkList;

Εισαγωγή στο Τέλος 0x2030 0x2000 0x2030 NULL NULL NULL NULL currentptr 0x2030 prevptr newnodeptr 0x2000

Εισαγωγή στο Τέλος 0x2030 0x2000 0x2030 0x2000 NULL NULL NULL currentptr 0x2030 prevptr newnodeptr 0x2000

Εισαγωγή στο Τέλος 0x2030 0x2000 0x2030 0x2000 NULL NULL 0x2030 currentptr 0x2030 prevptr newnodeptr 0x2000

Εισαγωγή Ενδιάμεσα 0x2030 NULL currentptr 0x2030 prevptr 0x2000 NULL NULL NULL 0x2000 newnodeptr

Εισαγωγή Ενδιάμεσα 0x2030 NULL currentptr 0x2030 prevptr 0x2000 2030 NULL NULL 0x2000 newnodeptr

Εισαγωγή Ενδιάμεσα 0x2030 NULL currentptr 0x2030 prevptr 0x2000 2030 3080 NULL 0x2000 newnodeptr

Εισαγωγή Ενδιάμεσα 0x2030 NULL currentptr 0x2030 prevptr 0x2000 2030 3080 NULL 0x2000 0x2000 newnodeptr

Εισαγωγή Ενδιάμεσα 0x2030 NULL currentptr 0x2000 prevptr 0x2000 2030 3080 NULL 0x2000 0x2000 newnodeptr

Διαγραφή από το Τέλος 0x2030 0x2030 NULL NULL currentptr oldnodeptr 0x2030 prevptr

Διαγραφή από το Τέλος 0x2030 NULL NULL NULL currentptr oldnodeptr 0x2030 prevptr

Διαγραφή από το Τέλος NULL NULL currentptr oldnodeptr 0x2030 prevptr

Διαγραφή Ενδιάμεσου 0x2030 0x2030 NULL NULL currentptr oldnodeptr prevptr

Διαγραφή Ενδιάμεσου 0x2030 0x2030 0x2030 NULL NULL currentptr oldnodeptr prevptr

Διαγραφή Ενδιάμεσου 0x2030 0x2030 0x2030 NULL NULL currentptr oldnodeptr prevptr

Διαγραφή Ενδιάμεσου 0x2030 0x2030 NULL NULL currentptr oldnodeptr prevptr

Απόδοση Υλοποιώντας μία List ADT με διπλά διασυνδεδεμένη λίστα Ο χώρος που χρησιμοποιείται από μία λίστα με n στοιχεία είναι O(n) Ο χώρος που χρησιμοποιείται από κάθε θέση της λίστας είναι O(1) Όλες οι λειτουργίες της List ADT εκτελούνται σε χρόνο O(1) Η διεργασία element() της Position ADT εκτελείται σε χρόνο O(1)

Παράδειγμα Να γράψετε µία αναδροµική και µία µη-αναδροµική διαδικασία InsertAfter(L, x, i) οι οποίες να παίρνουν ως δεδοµένο εισόδου µια κυκλική διπλά συνδεδεµένη λίστα L, και να εισάγουν το στοιχείο x µετά από το i-οστό στοιχείο της λίστας. Να συγκρίνετε τις δύο διαδικασίες ως προς τον χρόνο εκτέλεσής τους και τον χώρο που χρησιµοποιούν. Υποθέτουµε πως οι λίστες είναι υλοποιηµένες χρησιµοποιώντας τις πιο κάτω δοµές. typedef struct Node{ type data; struct node *next; struct node *prev; } node; typedef struct List{ node *head; } list; Υποθέτουµε ότιτοπεδίοtop της λίστας δείχνει το πρώτο στοιχείο της λίστας. Επίσης υποθέτουµε ότιαντοi είναι µεγαλύτερο από το µέγεθος της λίστας, τότε το στοιχείο προς εισαγωγή εισάγεται στην τελευταία θέση της λίστας.

Μη-αναδροµική εκδοχή InsertAfter(list *L, type x, int i){ p = (node *) malloc (sizeof(node)); p->data = x; q = L->top; if (q == NULL) p->next = p; p->prev = p; L->top = p; return; if (i == 0) L->top = p; j = 1; while (j<=i AND q->next!= L->top) q = q->next; j++; p->next = q->next; p->next)->prev = p; q->next = p; p->prev = q; }

Aναδροµική εκδοχή RecInsertAfter (list *L, type x, int i){ if (L->top == NULL) p = (node *) malloc (sizeof(node)); p->data = x; p->next = p; p->prev = p; L->top = p; elseif (i == 0) p = (node *) malloc (sizeof(node)); p->data = x; p->next = L->top; p->prev = L->top->prev; p->next->prev = p; p->prev->next = p L->top = p; else RecInsAfter(L, L->top, x, i); } RecInsAfter(list *L, node *q, type x, int i){ if (i == 0 OR q->next == L->top) p = (node *) malloc (sizeof(node)); p->data = x; p->next = q- >next; (p->next)->prev = p; q->next = p; p->prev = q; else RecInsAfter(L, q- >next, i-1) }

Σύγκριση Προφανώς και οι δύο αλγόριθµοι είναι της τάξης Ο(n), όπου n είναι ο αριθµός κόµβων της λίστας. O αναδροµικός αλγόριθµος είναι όµως λιγότερο αποδοτικός από άποψη χώρου (και χρόνου). Αυτό οφείλεται στο ότι για κάθε αναδροµική κλήση της διαδικασίας δεσµεύεται επιπλέον χώρος για τις παραµέτρους και τις τοπικές µεταβλητές των κλήσεων. Κατά συνέπεια, κατά την επεξεργασία του τελευταίου κόµβου της λίστας θα υπάρχουν σε κατάσταση αναµονής n 1 κλήσεις (όπου n είναι το µέγεθος της λίστας) που αφορούν όλους τους προηγούµενους κόµβους και για κάθε κλήση θα υπάρχει δεσµευµένη µνήµη για όλες τις παραµέτρους, τοπικές µεταβλητές, κλπ.