Πανεπιστηµιο Πειραιως Σχολη Τεχνολογιων Πληροφορικης και Επικοινωνιων Τµηµα Ψηφιακων Συστηµατων οµές εδοµένων 2015-2016 1η Εργασία Χρήστος ουλκερίδης Ορέστης Τελέλης 1 Περιγραφή Στην εργασία καλείστε να υλοποιήσετε µία δοµή Πολυσυνδεδεµένης Λίστας (Miltilinked List MlList) ειδικού σκοπού. Μια MlList είναι µια συλλογή κόµβων που συνδέονται «γραµµικά» σε δοµή (απλά συνδεδεµένης) λίστας µε πάνω από έναν τρόπους, ώστε να σχηµατίζουν ισάριθµες διαφορετικές λίστες. Ενα τετριµένο παράδειγµα MlList είναι η ιπλά Συνδεδεµένη Λίστα που συζητήθηκε στο µάθηµα, η οποία συνδέει τους κόµβους σε µια διάταξη και στην αντίστροφή της. Η MlList της εργασίας είναι τριπλά συνδεδεµένη λίστα µε κεφαλή: αναπαριστά τρεις (3) διαφορετικές (απλά συνδεδεµένες) λίστες επί της ίδιας συλλογής κόµβων. Καθεµία λίστα αναπα- ϱιστά το αποτέλεσµα µίας από τις πράξεις ένωση :, τοµή :, συµµετρική διαφορά :, επί υποτιθέµενης συλλογής k 1 δυναµικών συνόλων (δηλαδή, συνόλων στα οποία εισάγονται και από τα οποία διαγράφονται στοιχεία). Η ένωση είναι το σύνολο που περιέχει όλα τα στοιχεία των k συνόλων. Η τοµή είναι το υποσύνολο των κοινών στοιχείων όλων των k συνόλων. Η συµµετρική διαφορά είναι το υποσύνολο των στοιχείων που ανήκουν σε περιττό πλήθος από τα k σύνολα. 1 Στη γενική περίπτωση, µια δοµή τύπου Ml- List δεν αναπαριστά τα σύνολα καθεαυτά, 2 πα- ϱά µόνο τα αποτελέσµατα των συνολοθεωρητικών πράξεων σε αυτά. Ωστόσο, έχει εσωτερικά αποθηκευµένο σε ένα πεδίο µόνο το πλήθος (ακέραιος k) των συνόλων, για τα οποία αναπαρι- C στά έκαστη από τις συνολοθεωρητικές πράξεις. A B A B C Ενα παράδειγµα µιας MlList για k = 3 σύνολα απεικονίζεται στο Σχ. 1. Η MlList υποστηρίζει τρεις ϐασικές λειτουργίες : Εισαγωγή Στοιχείου : Καλείται από τον χρήστη της δοµής MlList οποτεδήποτε αυτός εισάγει ένα C στοιχείο σε ένα από τα k σύνολα. Κάθε διαφο- A B A B C ϱετική κλήση εισαγωγής στην MlList του ίδιου στοιχείου, ϑεωρούµε ότι αντιστοιχεί σε εισαγωγή του στοιχείου σε ένα διαφορετικό από τα k 1 Γενίκευση της πράξης Αποκλειστικό Η (Exclusive OR - XOR) σε περισσότερα από 2 σύνολα. 2 Εκτός αν k = 1: τότε έκαστη από τις τρεις λίστες µιας MlList περιέχει τα στοιχεία του µοναδικού συνόλου. 1
A = { 1, 3, 5, 6 }, B = { 2, 3, 4, 6, 7 }, C = { 1, 3, 5, 6, 7 } head 1 4 2 5 3 6 7 Σχήµα 1: Παράδειγµα µιας MlList για τρία δεδοµένα σύνολα A, B, C. Οι σύνδεσµοι µεταξύ των κόµβων είναι επισηµειωµένοι µε τη συνολοθεωρητική πράξη της οποίας τη λίστα υλοποιούν. Η σειρά των κόµβων στις λίστες δεν είναι σηµαντική. σύνολα. Ωστόσο, η MlList περιέχει µόνο έναν κόµβο για το στοιχείο αυτό, που δηµιουργείται την πρώτη ϕορά εισαγωγής του στοιχείου. Σε κάθε κόµβο υπάρχει ένας µετρητής, που µετρά το πλήθος των διαφορετικών πράξεων εισαγωγής που έχουν συµβεί για το ίδιο στοιχείο που απο- ϑηκεύει ο κόµβος. Εφόσον κληθεί εισαγωγή του ίδιου στοιχείου περισσότερες από k ϕορές, η πράξη εισαγωγής της MlList απλώς «αποτυγχάνει» (επιστρέφοντας µια κατάλληλη τιµή στο χρήστη). Μία «επιτυχηµένη» πράξη πολλοστής εισαγωγής του ίδιου στοιχείου, ενηµερώνει την τιµή του µετρητή και, ανάλογα µε τη (νέα) τρέχουσα τιµή του, ϑα πρέπει να συνδέει/αποσυνδέει τον κόµβο του στοιχείου κατάλληλα στις/από τις τρεις αναπαριστώµενες λίστες της MlList. ηλαδή, την πρώτη ϕορά εισαγωγής του στοιχείου στην MlList, δηµιουργείται ένας κόµβος για αυτό, µε µετρητή που έχει τιµή 1, και συνδέεται στη λίστα ένωσης. Οταν το στοιχείο έχει εισαχθεί k ϕορές στην MlList, ϑα πρέπει ο κόµβος του να συνδέεται στη λίστα τοµής (στην k-στή εισαγωγή). Οταν το στοιχείο έχει εισαχθεί περιττό πλήθος ϕορών, ϑα πρέπει ο κόµβος του να συνδέεται στη λίστα συµµετρικής διαφοράς ϑα πρέπει να αποσυνδέεται από τη λίστα αυτή, όταν το πλήθος ϕορών εισαγωγής του στοιχείου γίνεται άρτιος. ιαγραφή Στοιχείου : Καλείται από τον χρήστη της δοµής MlList οποτεδήποτε αυτός διαγράφει το στοιχείο από κάποιο από τα k σύνολα. Κάθε διαφορετική κλήση της διαγραφής του ίδιου στοιχείου ϑεωρούµε ότι αντιστοιχεί σε διαγραφή του στοιχείου από διαφορετικό σύνολο. Ο µετρητής σε κάθε κόµβο της MlList χρησιµοποιείται µε αντίστροφο τρόπο, από ότι στην πράξη εισαγωγής της MlList. Ο κόµβος της MlList που αποθηκεύει το στοιχείο δε διαγράφεται από τη λίστα ένωσης, εκτός αν ο µετρητής γίνει 0. Σε κάθε άλλη περίπτωση, ο µετρηρής µειώνεται κατά 1 και ο κόµβος αποσυνδέεται ή συνδέεται από τις/στις λίστες τοµής και συµµετρικής διαφοράς, ανάλογα µε την τρέχουσα (νέα) τιµή του µετρητή. Αυτές ϑεωρούνται «επιτυχηµένες» διαγραφές. Εφόσον η διαγραφή ενός συγκεκριµένου στοιχείου κληθεί περισσότερες από k ϕορές ή από όσες ϕορές έχει κληθεί η εισαγωγή του ίδιου στοιχείου, η διαγραφή απλώς «αποτυγχάνει» (επιστρέφοντας µια κατάλληλη ενδεικτική τιµή στο χρήστη). Αναζήτηση Στοιχείου : Η αναζήτηση ενός στοιχείου µπορεί να γίνει από τον χρήστη σε ο- ποιαδήποτε από τις τρεις αναπαριστώµενες λίστες, ένωσης, τοµής, ή συµµετρικής διαφοράς. Ο χρήστης της λειτουργίας αυτής µπορεί να προσδιορίζει τη λίστα στην οποία ϑα γίνει η αναζήτηση και το στοιχείο που αναζητά σε αυτήν. 2
2 Ζητούµενα Εργασίας Υλοποίηση. Θα επαυξήσετε δεδοµένο κώδικα για την υλοποίηση της δοµής MlList που πε- ϱιγράφηκε, ο οποίος επεξηγείται στο σύντοµο Παράρτηµα της εκφώνησης. Συγκεκριµένα, ϑα χρειαστεί να υλοποιήσετε τις ακόλουθες µεθόδους της κλάσης MLList: public boolean insert(int id, Object data); Εισάγει στην MlList τα δεδοµένα του χρήστη (data) µε κλειδί id. Να υποθέσετε ότι κάθε διαφορετικό ακέραιο κλειδί id προσδιορίζει µοναδικά το αντικείµενο data, ώστε όλοι οι έλεγχοι που απαιτούνται για την πράξη της εισαγωγής (και της διαγραφής, παρακάτω) ϑα γίνονται µε ϐάση το δεδοµένο κλειδί id. Σε περίπτωση επιτυχίας της πράξης εισαγωγής, η insert ϑα επιστρέφει true, διαφορετικά, ϑα επιστρέφει false. Ενηµερώνει τις τρεις αναπαριστώµενες λίστες κατάλληλα, όπως περιγράφηκε προηγουµένως. public Object delete(int id); ιαγράφει (µία ϕορά) από την MlList το στοιχείο µε κλειδί id. Αν δεν υπάρχει κόµβος στην MlList µε το δεδοµένο κλειδί id, απλώς επιστρέφει null. ιαφορετικά, ενηµερώνει τις τρεις αναπαριστώµενες λίστες κατάλληλα, όπως περιγράφηκε προηγουµένως, και επιστρέφει τα δεδοµένα του χρήστη (τύπου Object) που είναι συσχετισµένα µε το κλειδί id και αποθηκεύονται στον σχετικό κόµβο της MlList. public Object find(mllnode.ltype ltype, int id); Αναζητά σε µία από τις 3 λίστες της MlList που προσδιορίζεται από το όρισµα ltype (δείτε Παράρτηµα για τον ορισµό του), τον κόµβο µε κλειδί id. Επιστρέφει αναφορά τύπου Object στα δεδοµένα του χρήστη, αν εντοπίσει τον κόµβο, διαφορετικά επιστρέφει null. Σηµαντικές Παρατηρήσεις : ίνονται οι κλάσεις MLLNode, που υλοποιεί τύπο κόµβου της MlList, και MLList, που υλοποιεί τον τύπο της MlList (δείτε το Παράρτηµα). Στην υλοποίησή σας : 1. δε ϑα τροποποιήσετε την κλάση MLLNode. 2. δε ϑα προσθέσετε πεδία ή public µεθόδους στην κλάση MLList. 3. µπορείτε να προσθέσετε private µεθόδους στην κλάση MLList. 4. µπορείτε να τροποποιήσετε τη main της (επίσης δεδοµένης) κλάσης MLListApp όπως επι- ϑυµείτε, προκειµένου να πειραµατιστείτε µε τον κώδικά σας. Τεχνική Αναφορά. Θα καταγράψετε σε ψευδοκώδικα την υλοποίηση των µεθόδων σας, ϑα ε- πεξηγήσετε τη λειτουργία τους και ϑα δικαιολογήσετε/σχολιάσετε αναλυτικά την πολυπλοκότητά τους. Συγκεκριµένα, η αναφορά ϑα περιλαµβάνει : 1. Εξώφυλλο, µε Ονοµατεπώνυµο, Αριθµό Μητρώου, Τίτλο Μαθήµατος, Τίτλο Εργασίας. 2. Για καθεµία από τις µεθόδους, µία ενότητα µε τίτλο, που ϑα περιέχει : τον ψευδοκώδικα (και για οποιαδήποτε «ϐοηθητική» private µέθοδο γράψατε), επεξηγήσεις στον ψευδοκώδικα και στη λειτουργία της υλοποίησής σας, ανάλυση πολυπλοκότητας, προτάσεις για ϐελτίωση του (ϑεωρητικού ή πρακτικού) χρόνου εκτέλεσης, εφόσον πιστεύετε ότι ϐελτιώνεται µέσω εναλλακτικών επιλογών στην υλοποίηση της δοµής, ή δικαιολόγηση της αντίθετης άποψης. Για την εκπόνηση της τεχνικής αναφοράς συστήνεται να ακολουθήσετε το πρότυπο που παρέχεται µαζί µε την εκφώνηση της εργασίας και τον δεδοµένο κώδικα. 3
3 ιαδικαστικά Θέµατα ΠΑΡΑ ΟΤΕΑ Θα πρέπει να παραδώσετε ένα αρχείο ΑΜ_Επώνυµο_ Ονοµα.zip (όπου ΑΜ ο α- ϱιθµός µητρώου) που ϑα περιλαµβάνει 2 αρχεία µόνο : 1. Το αρχείο πηγαίου κώδικα MLList.java, επαρκώς σχολιασµένο. Προσοχή : σχόλια στα ελληνικά, µόνο σε κωδικοποίηση UTF-8. Άλλες κωδικοποιήσεις (ISO-8859-7, Windows-1253) απορρίπτονται από τον Java Compiler. Eclipse/Netbeans: δεξί click στο Project, επιλογή Properties και, στην ιδιότητα «Encoding», επιλέγετε UTF-8. 2. Την τεχνική αναφορά σας σε µορφή pdf. ΘΑ ΑΓΝΟΗΘΕΙ κάθε άλλη µορφή εγγράφου. ΠΑΡΑ ΟΣΗ αποκλειστικά µέσω της πλατφόρµας «ΕΥ ΟΞΟΣ» του τµήµατος, έως και την 11/12/2015, 23:59. Ανεβάστε το ΑΜ_Επώνυµο_ Ονοµα.zip στην περιοχή «Εργασίες». ΕΡΩΤΗΣΕΙΣ/ΑΠΟΡΙΕΣ/ ΙΕΥΚΡΙΝΙΣΕΙΣ αποκλειστικά µέσα από την Περιοχή Συζήτησης «ΕΡ- ΓΑΣΙΑ 1» της πλατφόρµας «ΕΥ ΟΞΟΣ». ε ϑα απαντηθούν Email µε απορίες. ΕΡΓΑΣΙΕΣ ΠΟΥ ΘΑ ΠΑΡΑ ΟΘΟΥΝ ΕΚΠΡΟΘΕΣΜΑ Η ΜΕ ΑΛΛΟ ΤΡΟΠΟ (Email, CD κ.λ.π.) Ε ΘΑ ΑΞΙΟΛΟΓΗΘΟΥΝ. ΒΑΘΜΟΛΟΓΗΣΗ Καθεµία από τις λειτουργίες εισαγωγής και διαγραφής συνεισφέρει 40% στο ϐαθµό της εργασίας. Η λειτουργία αναζήτησης συνεισφέρει 20%. Η εργασία µετρά 20% στον τελικό ϐαθµό (εφόσον το γραπτό σας ϐαθµολογηθεί µε τουλάχιστον 4). Φτωχή / υσανάγνωστη τεκµηρίωση ή έλλειψη αυτής στην αναφορά, για κάποια λειτουργία, επιφέρει άµεση απώλεια 50% του µέγιστου δυνατού ϐαθµού για τη λειτουργία αυτή. Η τεχνική αναφορά ή τµήµατα αυτής δε ϑα ληφθούν υπόψην στη ϐαθµολόγηση αν δε συνοδεύονται από κώδικα που µεταγλωττίζεται και εκτελείται. Η εργασία είναι αυστηρά ατοµική. Αντιγραφή στον κώδικα και/η στην τεχνική αναφο- ϱά επιφέρει άµεσο µηδενισµό της εργασίας. Οι εργασίες ϑα ελεγχθούν (όλες ανά Ϲεύγη). 4 Παράρτηµα : Τεκµηρίωση εδοµένου Κώδικα Ακολουθεί σύντοµος σχολιασµός του δεδοµένου κώδικα. Παρακάτω προβάλλονται µόνο πεδία και µέθοδοι των κλάσεων που ϑα χρειαστείτε (ή που ίσως χρειαστείτε). εν προβάλλεται επιπλέον δεδοµένος κώδικας που υλοποιεί λειτουργικότητα : επισηµειώνεται µε /*... */. Στα σηµεία που επισηµειώνονται µε /* your code */ ϑα πρέπει να εισάγετε τον δικό σας κώδικα. Κλάση Κόµβου της MlList Η κλάση MLLNode αναπαριστά έναν κόµβο της MlList. Περιέχει τα public πεδία id (κλειδί, τύπου int), data (δεδοµένα, τύπου Object) και count (µετρητής, τύπου int), και µια ειδική private δοµή τριών αναφορών σε αντικείµενα τύπου MLLNode (δεν προβάλλεται). Καθεµία από αυτές τις αναφορές δείχνει στον επόµενο του κόµβου, σε µία από τις τρεις αναπαριστώµενες λίστες : ένωσης, τοµής, συµµετρικής διαφοράς. Μπορείτε να προσβαίνετε και να µεταβάλλετε τις αναφορές αυτές µε χρήση των µεθόδων getnext και setnext αντίστοιχα. Για να διευκρινίσετε τη λίστα (από τις τρεις αναπαριστώµενες) για την οποία χρειάζεστε πρόσβαση στον επόµενο ενός δεδοµένου κόµβου, χρησιµοποιείτε τις τιµές τύπου MLLNode.LType. Π.χ.: MLLNode nextnode = node.getnext(mllnode.ltype.any); [επόµενος στην ένωση] MLLNode nextnode = node.getnext(mllnode.ltype.all); [επόµενος στην τοµή] MLLNode nextnode = node.getnext(mllnode.ltype.xor); [επόµενος στη συµ. διαφορά] 4
class MLLNode { public enum LType {ANY, ALL, XOR}; public int id; public Object data; public int count; /*... */ public static MLLNode create(int id, Object data) { /*... */ } public MLLNode getnext(ltype type) { /*... */ } public MLLNode setnext(ltype type, MLLNode node) { /*... */ } public void display() { /*... */ } } Με παρόµοιο τρόπο µε τη getnext µπορείτε να χρησιµοποιείτε και τη setnext. Αν node1, node2 είναι δύο αντικείµενα τύπου MLLNode, µπορείτε π.χ. να γράψετε : node1.setnext(mllnode.ltype.xor, node2); ώστε να ϑέσετε τον node2 σαν επόµενο του node1 στη λίστα συµµετρικής διαφοράς. Για τη δηµιουργία νέου κόµβου αποθήκευσης ενός στοιχείου µε κλειδί id και δεδοµένα data ϑα πρέπει να χρησιµοποιείτε τη static µέθοδο create, όπως π.χ. ακολούθως : MLLNode newnode = MLLNode.create(id,data); Προσοχή : ο constructor της κλάσης είναι private, δεν επιτρέπεται η χρήση του. Τέλος, δίνεται και µια µέθοδος display για την εκτύπωση των περιεχοµένων του κόµβου. Κλάση Υλοποίησης της MlList Η κλάση MLList έχει 2 private πεδία. Ο ακέραιος nbsets κρατά το πλήθος των συνόλων για τα οποία η MlList αναπαριστά τις πράξεις,,. Το αντικείµενο head είναι ο κόµβος-κεφαλή. class MLList { private int nbsets; private MLLNode head; } public MLList(int _nbsets) { /*... */ } public boolean isempty(mllnode.ltype ltype) { /*... */ } public void display(mllnode.ltype ltype) { /*... */ } /* your code (private methods only) */ public Object find(mllnode.ltype ltype, int id) { /* your code */ } public boolean insert(int id, Object data) { /* your code */ } public Object delete(int id) { /* your code */ } ίνονται υλοποιηµένες οι µέθοδοι isempty, display που δέχονται σαν όρισµα τιµή τύπου MLLNode.LType και ο constructor της κλάσης. Η isempty επιστρέφει true αν η λίστα που προσδιορίζεται από το όρισµα ltype είναι κενή, διαφορετικά επιστρέφει false. Η display εκτυπώνει τα περιεχόµενα της λίστας που προσδιορίζεται από το όρισµα ltype (για κάθε κόµβο, το id ακόλουθούµενο από το count εντός παρενθέσεως). Ενα παράδειγµα εκτύπωσης της display: [ 2 (1) 18 (1) 17 (1) 0 (1) 14 (1) 9 (2) 8 (1) 12 (2) 5 (1) ] Κλάση Εφαρµογής MLListApp ίνεται µια κλάση εφαρµογής MLListApp, που περιέχει µια main µέθοδο. Η main απλώς κατασκευάζει ένα αντικείµενο τύπου MLList, εκτελεί τυχαίες πράξεις εισγωγής και διαγραφής σε αυτό και το εκτυπώνει. Μπορείτε να τη µεταβάλλετε όπως ϐολεύει καλύτερα, για την ανάπτυξη του κώδικά σας. 5