4 ΔYNAMIKEΣ ΔOMEΣ ΔEΔOMENΩN

Σχετικά έγγραφα
Δηµοσθένης Σταµάτης Τµήµα Πληροφορικής T.E.I. ΘΕΣΣΑΛΟΝΙΚΗΣ

ΑΤΕΙ ΘΕΣΣΑΛΟΝΙΚΗΣ. Δηµοσθένης Σταµάτης Τµήµα Πληροφορικής

Συνδεδεμένη Λίστα (Linked List)

Συνδεδεμένη Λίστα ΣΛ null VK 23

ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ µε JAVA

Oι βασικές πράξεις (λειτουργίες) που ορίζονται για τον τύπο στοίβα αναφέρονται παρακάτω:

Δομές Δεδομένων & Ανάλυση Αλγορίθμων. 3ο Εξάμηνο. Ουρά (Queue) Υλοποίηση της με τη βοήθεια πίνακα.

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

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

Δηµοσθένης Σταµάτης Τµήµα Πληροφορικής T.E.I. ΘΕΣΣΑΛΟΝΙΚΗΣ

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

public class ArrayStack implements Stack {

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

Περιεχόµενα. 1 Εισαγωγή στις οµές εδοµένων 3. 2 Στοίβα (Stack) 5

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

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

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

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

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

Δομές Δεδομένων - Εργαστήριο 2. Λίστες

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

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

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

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

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

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

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

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

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

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

HY-252 Αντικειμενοστραφής Προγραμματισμός. Χειμερινό Εξάμηνο 2012 Διδάσκων: Χριστοφίδης Βασίλης. Ημερομηνία Παράδοσης: 16/11/2012

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

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

2 ΓΡΑΜΜΙΚΕΣ ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ

public class ArrayQueue implements Queue {

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

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

Αντικειμενοστρέφεια. Henri Matisse, Harmony in Red, Κωστής Σαγώνας Νίκος Παπασπύρου

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

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

Ευφυείς Τεχνολογίες ----Πράκτορες

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

Δοµές Δεδοµένων. 6η Διάλεξη Αναδροµικές Εξισώσεις και Αφηρηµένοι Τύποι Δεδοµένων. Ε. Μαρκάκης

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

Το ισχυρό πλεονέκτηµα των απλών µη ταξινοµηµένων πινάκων που είναι η γρήγορη εισαγωγή, αναιρείται αν απαγορεύονται τα διπλότυπα.

Πρόγραµµα 9.1 Πέρασµα δεδοµένων στην µνήµη

Συγκρίσιμα Αντικείμενα (comparable)

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

Κλάσεις στη Java. Παύλος Εφραιμίδης. Java Κλάσεις στη Java 1

Δοµές Δεδοµένων. 7η Διάλεξη Αφηρηµένοι Τύποι Δεδοµένων. Ε. Μαρκάκης

Κλάσεις στη Java. Στοίβα - Stack. Δήλωση της κλάσης. ΗκλάσηVector της Java. Ηκλάση Stack

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

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

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

ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ. Πίνακες Συµβόλων Κεφάλαιο 12 ( ) Ε. Μαρκάκης Επίκουρος Καθηγητής

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

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

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

Οι βασικές λειτουργίες (ή πράξεις) που γίνονται σε μια δομή δεδομένων είναι:

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

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

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

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

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

Από τη UML στον Κώδικα. Μέρος Α

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

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

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

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

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

Ουρά Προτεραιότητας (priority queue)

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

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

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

Οι λίστες, χάνοντας τα πλεονεκτήματα των πινάκων, λύνουν προβλήματα που παρουσιάζουν οι πίνακες

Δοµές Δεδοµένων. 11η Διάλεξη Ταξινόµηση Quicksort και Ιδιότητες Δέντρων. Ε. Μαρκάκης

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

POINTERS, AGGREGATION, COMPOSITION

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

Ενότητα 2 Στοίβες Ουρές - Λίστες. ΗΥ240 - Παναγιώτα Φατούρου 1

Δομές Δεδομένων. Δημήτρης Μιχαήλ. Υλοποίηση Δυαδικού Σωρού σε γλώσσα Java. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Στοίβες Ουρές - Λίστες

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

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

ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ. Βασικές Ιδιότητες και Διάσχιση Κεφάλαιο 5 ( και ) Ε. Μαρκάκης Επίκουρος Καθηγητής

2.2.5 ΑΝΑΠΑΡΑΣΤΑΣΗ ΑΛΓΟΡΙΘΜΟΥ

ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ. Στοιχειώδεις Δοµές Δεδοµένων Λίστες Κεφάλαιο 3 (3.3, 3.4, 3.7) Ε. Μαρκάκης Επικ. Καθηγητής

Οικονοµικό Πανεπιστήµιο Αθηνών. Τµήµα Πληροφορικής. Φθινοπωρινό Εξάµηνο Δοµές Δεδοµένων - Εργασία 2. Διδάσκων: E. Μαρκάκης

Αντικειµενοστρεφής Προγραµµατισµός

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

Αντικειμενοστρεφής Προγραμματισμός

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

2.1 Αντικειµενοστρεφής προγραµµατισµός

5 ΔΕΝΤΡΑ (Trees) Σχήµα 5.1 : ενδροειδής αναπαράσταση αρχείων στα Windows. έντρα. \ {root directory} Accessories. Program Files.

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

Προγραμματισμός Υπολογιστών με C++

Λίστες παράλειψης (skip lists)

υαδικό έντρο Αναζήτησης (BSTree)

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

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

Transcript:

4 ΔYNAMIKEΣ ΔOMEΣ ΔEΔOMENΩN Yπάρχει ένας αριθµός προγραµµατιστικών προβληµάτων, τα οποία είναι δύσκολο να επιλυθούν µε τη βοήθεια των στατικών δοµών δεδοµένων που αναφέραµε µέχρι τώρα. Aυτό γιατί οι δοµές αυτές είναι προκαθορισµένες και παραµένουν σταθερές σε όλη τη διάρκεια της εκτέλεσης του προγράµµατος. Για παράδειγµα εάν θεωρήσουµε την παρακάτω δήλωση της µεταβλητής A. int[ ] A = new int[1000]; Ο αριθµός των στοιχείων του πίνακα Α που είναι διαθέσιµα κατά τη διάρκεια εκτέλεσης του προγράµµατος θα είναι ακριβώς 1000, κάτι που προκαθορίζεται όταν το πρόγραµµα µεταγλωττίζεται. Eπί πλέον ο χώρος µνήµης που απαιτείται για την αποθήκευση των στοιχείων αυτών είναι επίσης προκαθορισµένος. H κατάσταση αυτή δεν αποτελεί πρόβληµα στην περίπτωση που γνωρίζουµε από την αρχή πόσα στοιχεία θα χρειαστούµε, αυτό όµως τις περισσότερες φορές δεν είναι εφικτό. Ένα δεύτερο πρόβληµα δηµιουργείται από το γεγονός ότι τα στοιχεία του πίνακα θεωρούνται συνεχόµενα. Έτσι εάν χρειαστεί να παρεµβάλουµε ένα στοιχείο ανάµεσα σε άλλα δύο (ανάγκη που προκύπτει, όταν θέλουµε για παράδειγµα να εισάγουµε µία τιµή σε έναν ταξινοµηµένο πίνακα χωρίς να αλλοιώσουµε την ιδιότητά του αυτή) πρέπει να καταφύγουµε στη χρονοβόρα διαδικασία αντιγραφής ενός µεγάλου πλήθους στοιχείων σε άλλη περιοχή του πίνακα. H λύση στα προβλήµατα αυτά µπορεί να δοθεί µε τη χρήση των δυναµικών δοµών δεδοµένων. 43

Mια δοµή δεδοµένων η οποία µπορεί να δηµιουργηθεί και να µετατρέπεται στη διάρκεια της εκτέλεσης του προγράµµατος αυξοµειώνοντας το µέγεθός της ή το χώρο που καταλαµβάνει στη µνήµη ονοµάζεται δυναµική δοµή δεδοµένων (dynamic data structure ). Μία τέτοια δυναµική δοµή δεδοµένων είναι η συνδεδεµένη λίστα (linked list), που εξετάζουµε στη συνέχεια. 4.1 ΛΙΣΤΕΣ Λίστα (list) είναι ένα διατεταγµένο σύνολο από 0 ή περισσότερα στοιχεία τα οποία, κατά κανόνα, είναι όλα του ίδιου τύπου. Μία λίστα διαφέρει από έναν πίνακα στο ότι το µέγεθός της είναι γενικά µεταβλητό. Συχνά παριστάνουµε µία λίστα παραθέτοντας τα στοιχεία της ως εξής: a 1, a 2,..., a n όπου n >= 0 και κάθε a i είναι κάποιου συγκεκριµένου τύπου. Ο αριθµός των στοιχείων της λίστας ονοµάζεται µήκος (length) της λίστας. Θεωρώντας ότι n >= 1, λέµε ότι το a 1 είναι το πρώτο στοιχείο της λίστας και το a n το τελευταίο. Εάν n = 0, τότε έχουµε την κενή λίστα (µία λίστα που δεν έχει κανένα στοιχείο). 4.1.1 Yλοποίηση Λίστας µε τη Bοήθεια Δεικτών Mια λίστα µπορεί να θεωρηθεί σαν µία συλλογή από κόµβους, οι οποίοι είναι συνδεδεµένοι µεταξύ τους. Kάθε κόµβος µπορεί να υλοποιηθεί µε τη βοήθεια µιας δυάδας πεδίων. Το πρώτο πεδίο περιλαµβάνει ένα στοιχείο της λίστας (την πληροφορία που σχετίζεται µε το στοιχείο αυτό) και το δεύτερο ένα δείκτη ο οποίος δείχνει στον επόµενο κόµβο της λίστας. Τα δύο αυτά πεδία µπορούν να οριστούν στα πλαίσια της κλάσης Node, η οποία δίνεται στη συνέχεια. Η δηµιουργία ενός καινούργιου κόµβου µπορεί να περιλαµβάνει αρχικά την περίπτωση ενός κενού κόµβου, ο οποίος δεν έχει καµία πληροφορία στο πεδίο item (= null) και δεν είναι συνδεδεµένος µε κανέναν άλλο κόµβο (next = null). Μπορεί όµως να περιλαµβάνει την περίπτωση που και τα δύο αυτά πεδία έχουν συγκεκριµένες τιµές κατά τη δηµιουργία τους. 44

class Node Object item; Node next; public Node( ) this(null,null); public Node(Object it, Node n) item = it; next = n; Oι λίστες που υλοποιούνται µε αυτό τον τρόπο ονοµάζονται συνδεδεµένες λίστες (linked lists). Η σχηµατική αναπαράσταση µίας τέτοιας λίστας η οποία περιλαµβάνει τρεις κόµβους δίνεται στο σχήµα 4.1: L null Σχήµα 4.1 : Συνδεδεµένη λίστα µε τρεις κόµβους Πρέπει να τονιστεί ότι στις συνδεδεµένες λίστες δεν υπάρχει άµεσος τρόπος πρόσβασης σε έναν οποιονδήποτε κόµβο της. Ο µόνος που «γνωρίζει» την ύπαρξη ενός κόµβου είναι ο προηγούµενός του, καθώς γνωρίζει τη διεύθυνση του σαν τιµή που είναι αποθηκευµένη στο πεδίο του next. Με την έννοια αυτή για να έχουµε πρόσβαση σε έναν κόµβο πρέπει να περάσουµε ακολουθιακά από όλους τους προηγούµενους αρχίζοντας από τον πρώτο. Ο πρώτος κόµβος της λίστας πρέπει οπωσδήποτε να «δεικνύεται» από µία µεταβλητή τύπου Node (η µεταβλητή L στο παράδειγµα του σχήµατος 4.1). Η µεταβλητή αυτή ονοµάζεται δείκτης (pointer). Στην περίπτωση της Java ο δείκτης αυτός δεν είναι 45

τίποτε άλλο από µία µεταβλητή τύπου αναφοράς (reference), µία µεταβλητή που αναπαριστά ένα αντικείµενο της κλάσης Node. O δείκτης στον πρώτο κόµβο χαρακτηρίζει τη συνδεδεµένη λίστα σαν δοµή δεδοµένων και πρέπει να παραµένει εκεί σε όλη τη διάρκεια εκτέλεσης του προγράµµατος που τη χειρίζεται. Δείκτες είναι επίσης όλες οι τιµές των πεδίων next όλων των κόµβων της συνδεδεµένης λίστας: δείχνουν στον επόµενο κόµβο. Το πεδίο του τελευταίου κόµβου έχει την τιµή null (δείχνει στο null). Στο παράδειγµα του σχήµατος 4.1: L.next είναι ο δείκτης που δείχνει στο δεύτερο κόµβο και L.next.next είναι ο δείκτης που δείχνει στον τρίτο κόµβο Οι πιο βασικές λειτουργίες που απαιτούνται για το χειρισµό µιας συνδεδεµένης λίστας ανήκουν σε µία από τις παρακάτω τρεις κατηγορίες: Επίσκεψη κάποιου κόµβου της συνδεδεµένης λίστας Προσθήκη ενός κόµβου στη συνδεδεµένη λίστα Διαγραφή ενός κόµβου από τη συνδεδεµένη λίστα Πρόσβαση σε κάποιο κόµβο της λίστας: Για να επισκεφθούµε κάποιον συγκεκριµένο κόµβο µίας λίστας (για να έχουµε πρόσβαση σ αυτόν) εργαζόµαστε ως εξής: Αρχικά τοποθετούµε έναν βοηθητικό δείκτη ο οποίος δείχνει στην αρχή της λίστας (σχ. 4.2α) Current = L; L Current... null Σχήµα 4.2α : Ο βοηθητικός δείκτης Current δείχνει στην αρχή της λίστας Στη συνέχεια µετακινούµε τον δείκτη Current στον επόµενο κόµβο Current = Current.next; ή ισοδύναµα (βλέπε κλάση Node στο τµήµα κώδικα 1) 46

Current = Current.getNext( ); Η παραπάνω διαδικασία µετακίνησης στον επόµενο κόµβο γίνεται επαναληπτικά όσες φορές χρειάζεται, ώστε να τοποθετηθούµε στον επιθυµητό κόµβο (σχ. 4.2β). L Current... null Σχήµα 4.2β : Ο βοηθητικός δείκτης Current δείχνει στον επιθυµητό κόµβο Εισαγωγή ενός νέου κόµβου στη λίστα: Για να τοποθετήσουµε έναν κόµβο σε µία συνδεδεµένη λίστα πρέπει να γνωρίζουµε τον προηγούµενό του ή ισοδύναµα να τον δείχνουµε µε τη βοήθεια ενός δείκτη τύπου Node, έστω C στο παράδειγµα του σχήµατος 4.3α. Στη συνέχεια η εισαγωγή ακολουθεί τα εξής βήµατα: Αρχικά δηµιουργούµε έναν καινούργιο κόµβο (σχ.4.3α) Β = new Node(T, null) όπου T η τιµή που θέλουµε να έχει το πεδίο πληροφορίας item του κόµβου. B C...... Σχήµα 4.3α : ηµιουργία του κόµβου Β προς εισαγωγή Στη συνέχεια συνδέουµε τον κόµβο αυτό µε τον επόµενο του C (σχ. 4.3β) Β.next = C. next; ή ισοδύναµα (βλέπε κλάση Node στο τµήµα κώδικα 1) B.setNext(C.getNext( )); 47

B C...... Σχήµα 4.3β : Ο επόµενος του κόµβου Β γίνεται ο επόµενος του C Τέλος κάνουµε επόµενο του κόµβου C τον κόµβο B (σχ. 4.3γ) C.next = B; ή ισοδύναµα C.setNext(B); B C...... Σχήµα 4.3γ : Ο επόµενος του κόµβου C γίνεται ο νέος κόµβος Β Διαγραφή ενός κόµβου από τη λίστα: Για να διαγράψουµε έναν κόµβο από µία συνδεδεµένη λίστα πρέπει επίσης, όπως και στην περίπτωση της εισαγωγής, να γνωρίζουµε τον προηγούµενό του ή ισοδύναµα να τον δείχνουµε µε τη βοήθεια ενός δείκτη τύπου Node, έστω C στο παράδειγµα του σχήµατος 4.4α. Στη συνέχεια διαγράφουµε τον επόµενο κόµβο του C παρακάµπτοντάς τον ως εξής: C.next = C.next.next; ή ισοδύναµα C.setNext(C.getNext( ).getnext( )) Η κατάσταση της λίστας πριν και µετά τη διαγραφή φαίνεται στα σχήµατα 4.4α και 4.4β. C...... Σχήµα 4.4α : Πριν τη διαγραφή του επόµενου κόµβου του C 48

C...... Σχήµα 4.4β : Μετά τη διαγραφή του επόµενου κόµβου του C Στα σχήµατα 4.5α,β και γ φαίνονται τρεις διαφορετικοί τρόποι αναπαράστασης µιας συνδεδεµένης λίστας. Οι δύο πρώτοι αναφέρονται στην απλά συνδεδεµένη λίστα, που έχουµε συζητήσει. L... null Σχήµα 4.5α : Απλά συνδεδεµένη λίστα µε πρόσβαση στην αρχή Στη δεύτερη περίπτωση φροντίζουµε επιπλέον να διατηρούµε έναν δείκτη στον τελευταίο κόµβο, για να έχουµε έτσι ευκολότερη πρόσβαση σε αυτόν. firstnode lastnode... null Σχήµα 4.5β : Απλά συνδεδεµένη λίστα µε πρόσβαση στην αρχή και στο τέλος Στην τρίτη περίπτωση αναφερόµαστε στη διπλά συνδεδεµένη λίστα, όπου κάθε κόµβος της διαθέτει ένα επιπλέον πεδίο τύπου Node το οποίο δείχνει στον προηγούµενο κόµβο της λίστας. 49

firstnode lastnode null... null Σχήµα 4.5γ : ιπλά συνδεδεµένη λίστα Στη συνέχεια δίνεται η υλοποίηση της συνδεδεµένης λίστας του σχήµατος 4.5β: Για τη λίστα αυτή ορίζουµε δύο δείκτες firstnode και lastnode που δείχνουν αντίστοιχα στον πρώτο και τελευταίο κόµβο της. Στην περίπτωση της κενής λίστας θεωρούµε ότι οι δύο αυτοί δείκτες δείχνουν στο null. Υπεύθυνη για τη διαχείριση της συνδεδεµένης λίστας είναι η κλάση LinkedList, στα πλαίσια της οποίας ορίζονται οι πράξεις: insertfirst: εισάγει ένα στοιχείο στην αρχή της λίστας insertlast: εισάγει ένα στοιχείο στο τέλος της λίστας removefirst: διαγράφει και επιστρέφει το πρώτο στοιχείο της λίστας removelast: διαγράφει και επιστρέφει το τελευταίο στοιχείο της λίστας isempty: ελέγχει εάν η λίστα είναι κενή size: επιστρέφει το µέγεθος (αριθµό κόµβων) της λίστας printlist: εκτυπώνει όλα τα στοιχεία της λίστας Στο τµήµα κώδικα 1 δίνεται η αναπαράσταση/υλοποίηση ενός κόµβου της συνδεδεµένης λίστας και στο τµήµα κώδικα 2 δίνεται η κλάση που υλοποιεί τη συνδεδεµένη λίστα. Θεωρούµε ότι οι κλάσεις Node και LinkedList βρίσκονται στο ίδιο πακέτο. Με την έννοια αυτή η κλάση LinkedList έχει πρόσβαση στα πεδίa item και next της Node. Εναλλακτικά, και για µια πιο ασφαλή υλοποίηση, θα έπρεπε: Τα πεδία item και next της κλάσης Node να δηλωθούν private και Στα πλαίσια της κλάσης LinkedList να γίνεται χρήση των πεδίων αυτών µε τη βοήθεια των µεθόδων getnext, setnext, getitem και setitem. 50

class Node //Ορισµός κόµβου µιας απλά συνδεδεµένης λίστας (linked list) Object item; Node next; public Node( ) this(null,null); public Node(Object it, Node n) item = it; next = n; public void setitem(object newitem) item = newitem; public void setnext(node newnext) next = newnext; public Object getitem( ) return(item); public Node getnext( ) return(next); Τµήµα Κώδικα 1 51

import java.io.*; public class LinkedList //Υλοποίηση µιάς απλά συνδεδεµένης λίστας (linked list) private Node firstnode, lastnode; public LinkedList( ) firstnode = lastnode = null; public Node getfirst( ) return firstnode; public Node getlast( ) return lastnode; public boolean isempty( ) return(firstnode == null); public void insertfirst(object newitem) if (isempty( )) firstnode = lastnode = new Node(newItem, null); else firstnode = new Node(newItem, firstnode); public void insertlast(object newitem) if (isempty( )) firstnode = lastnode = new Node(newItem, null); else lastnode = lastnode.next = new Node(newItem, null); 52

public Object removefirst( ) throws ListEmptyException Object removeitem; if (isempty( )) throw new ListEmptyException("Empty List!!!"); removeitem = firstnode.item; if (firstnode == lastnode) firstnode = lastnode = null; else firstnode = firstnode.next; return removeitem; public Object removelast( ) throws ListEmptyException Object removeitem; if (isempty( )) throw new ListEmptyException("Empty List!!!"); removeitem = lastnode.item; if (firstnode == lastnode) firstnode = lastnode = null; else Node current = firstnode; while (current.next!= lastnode) current = current.next; lastnode = current; current.next = null; return removeitem; public void printlist( ) if (isempty( )) System.out.println("Empty List"); else Node current = firstnode; while (current!= null) System.out.print(current.item.toString() + " "); current = current.next; 53

System.out.println("\n"); ------------- public class ListEmptyException extends RuntimeException public ListEmptyException(String err) super(err); Τµήµα Κώδικα 2 Στο τµήµα κώδικα 3 δίνεται η υλοποίηση της µεθόδου για την ταξινόµηση των στοιχείων µιας συνδεδεµένης λίστας (θεωρήστε ότι ο τύπος του item είναι String). public class ListToSort extends LinkedList public ListToSort() super(); public LinkedList SortList() Node trace, current, min; trace = getfirst(); while (trace!=null) current = trace; min = trace; while (current!=null) if ((current.getitem()).compareto(min.getitem())<0) min=current; current = current.getnext(); //endwhile current String temp = trace.getitem(); trace.setitem(min.getitem()); min.setitem(temp); trace = trace.getnext(); //endwhile trace return this; Τµήµα Κώδικα 3 54

4.2 Υλοποίηση Στοίβας και Ουράς µε τη βοήθεια συνδεδεµένης λίστας Η υλοποίηση των δοµών δεδοµένων στοίβα και ουρά µε τη βοήθεια ενός πίνακα είχε το µειονέκτηµα της συγκεκριµένης χωρητικότητας η οποία πρέπει να επιλέγεται κατά στιγµή της δηµιουργίας. Στο τµήµα κώδικα 3 φαίνεται ο τρόπος µε τον οποίο µπορεί να χρησιµοποιηθεί η δοµή δεδοµένων συνδεδεµένη λίστα για την υλοποίηση µίας συνδεδεµένης στοίβας (linked stack). Η υλοποίηση της στοίβας σε αυτή την περίπτωση γίνεται µε την τεχνική της σύνθεσης (composition) καθώς χρησιµοποιείται µία άλλη δοµή τοπικά στην κλάση. H τεχνική αυτή ονοµάζεται και εξουσιοδότηση (delegation) public class LinkedStack implements Stack // Υλοποίηση στοίβας µε την τεχνική της σύνθεσης (composition) // H τεχνική αυτή ονοµάζεται και Εξουσιοδότηση (Delegation) private LinkedList S; public LinkedStack( ) S=new LinkedList(); public int size() return S.size(); public boolean isempty() return S.isEmpty(); public Object top( ) throws StackEmptyException Object temp; if (S.isEmpty()) throw new StackEmptyException("Empty Stack!"); temp = S.removeFirst(); S.insertFirst(temp); return temp; 55

public void push(object item) S.insertFirst(item); public Object pop( ) throws StackEmptyException try return S.removeFirst(); catch (ListEmptyException str) throw new StackEmptyException("EmptyStack"); Τµήµα κώδικα 4 Στο τµήµα κώδικα 5 δίνεται µία εναλλακτική υλοποίηση της στοίβας όπου χρησιµοποιείται µόνον η κλάση Node. import Node; public class LinkedStack2 implements Stack // Υλοποίηση της στοίβας µε τη χρήση µόνον της κλάσης Node private Node top; private int size; public LinkedStack2( ) top = null; size = 0; public int size( ) return size; public boolean isempty( ) return (top == null); 56

public Object top( ) throws StackEmptyException if (isempty( )) throw new StackEmptyException("Empty Stack!"); return top.getitem(); public void push(object item) Node newtop = new Node( ); newtop.setitem(item); newtop.setnext(top); top = newtop; size++; public Object pop( ) throws StackEmptyException try Object temp = top.getitem(); top = top.getnext(); size--; return temp; catch (ListEmptyException str) throw new StackEmptyException("EmptyStack"); Τµήµα κώδικα 5 Στο τµήµα κώδικα 6 δίνεται η υλοποίηση της στοίβας σαν επέκταση της κλάσης LinkedList µε τη µέθοδο της κληρονοµικότητας. public class LinkedStack3 extends LinkedList implements Stack // Υλοποίηση της στοίβας µε τη µέθοδο της κληρονοµικότητας // από την κλάση LinkedList // Ερώτηση: Τί γίνεται µε τις άλλες µεθόδους της LinkedList? 57

public LinkedStack3( ) super( ); public int size() return super.size(); public boolean isempty() return super.isempty(); public Object top( ) throws ListEmptyException Object temp; temp = removefirst(); insertfirst(temp); return temp; public void push(object item) insertfirst(object); public Object pop( ) throws ListEmptyException return removefirst(); Τµήµα κώδικα 6 Στο τµήµα κώδικα 7 δίνεται η υλοποίηση της δοµής δεδοµένων ουρά µε τη βοήθεια µίας συνδεδεµένης λίστας. Χρησιµοποιείται η τεχνική της σύνθεσης. Με αντίστοιχους τρόπους µε αυτούς της στοίβας µπορεί αντίστοιχα να υλοποιηθεί και η ουρά µε διαφορετικούς τρόπους. 58

public class LinkedQueue implements Queue // Υλοποίηση ουράς µε την τεχνική της σύνθεσης (composition) private LinkedList Q; public LinkedQueue( ) Q=new LinkedList(); public int size() return Q.size(); public boolean isempty() return Q.isEmpty(); public Object front( ) throws QueueEmptyException Object temp; if (Q.isEmpty()) throw new QueueEmptyException("Empty Queue!"); temp = Q.removeFirst(); Q.insertFirst(temp); return temp; public void enqueue(object item) Q.insertLast(item); public Object dequeue( ) throws QueueEmptyException try return Q.removeFirst(); catch (ListEmptyException str) throw new QueueEmptyException("EmptyQueue"); Τµήµα κώδικα 7 59