#3. Στατικές γραμμικές λίστες, συνδεδεμένες γραμμικές λίστες, γραμμικές λίστες της STL

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

#4. Heaps (σωροί), η ταξινόμηση HeapSort, η δομή std::priority_queue της STL

Standard Template Library (STL)

Φροντιςτήριο. Linked-List

Ερώτημα Α 1. Να γράψετε τις εντολές που πραγματοποιούν τα ακόλουθα:

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

Δομές Δεδομένων και Αλγόριθμοι (Γ εξάμηνο) Τμήμα Μηχανικών Πληροφορικής ΤΕ, ΤΕΙ Ηπείρου. Άσκηση εργαστηρίου #6 (Υλοποίηση δυαδικού δένδρου αναζήτησης)

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

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

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

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

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

#2. Templates, η βιβλιοθήκη STL, μέτρηση χρόνου εκτέλεσης κώδικα, αλγόριθμοι ταξινόμησης, αλγόριθμοι αναζήτησης

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

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

Μάθημα 22: Δυαδικά δέντρα (Binary Trees)

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

Προγραμματισμός Υπολογιστών με C++ Φύλλο Διαγωνίσματος Ακαδημαϊκό εξάμηνο: Χειμερινό

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

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

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

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

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

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

ΑΣΚΗΣΕΙΣ ΓΙΑ ΤΟ ΕΡΓΑΣΤΗΡΙΟ 2

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

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

HY150a Φροντιστήριο 3 24/11/2017

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

Κλήση Συναρτήσεων ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΕΩΝ. Γεώργιος Παπαϊωάννου ( )

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

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

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

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

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

Ονοματεπώνυμο και ΑΜ: Είχα παραδώσει εργασίες τα προηγούμενα ακαδημαϊκά έτη: ΚΑΛΗ ΕΠΙΤΥΧΙΑ!

Αναφορές, είκτες και Αλφαριθμητικά

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

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

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

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

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

ΑΣΚΗΣΕΙΣ ΓΙΑ ΤΟ ΕΡΓΑΣΤΗΡΙΟ 1

19. ΠΡΟΤΥΠΑ (TEMPLATES)

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

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

Προγραμματισμός Ι. Κλάσεις και Αντικείμενα. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

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

Γ7.2 Συμβολοσειρές (Strings) Γ Λυκείου Κατεύθυνσης

Συµβολοσειρές - Strings

Σημειώσεις όγδοης εβδομάδας

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

Δομές Δεδομένων και Αλγόριθμοι ΜΕΡΟΣ Γ Εργαστήριο (C++) Τ.Ε.Ι. Ηπείρου - Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Χρήστος Γκόγκος

Προηγµένα Θέµατα Τεχνολογιών Υλοποίησης Αλγορίθµων

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

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

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

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

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

Προγραμματισμός Αναδρομή

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

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

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

Προγραμματισμός Αναδρομή

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

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

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

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

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

Κατανεμημένα και Παράλληλα Συστήματα (εργαστήριο) Παραδείγματα με openmp

Δυναμική δέσμευση και αποδέσμευση μνήμης. Προγραμματισμός II 1

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

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

ΥΠΟΛΟΓΙΣΤΕΣ ΙΙ. Τι περιλαμβάνει μια μεταβλητή; ΔΕΙΚΤΕΣ. Διεύθυνση μεταβλητής. Δείκτης

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

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

ΕΡΓΑΣΤΗΡΙΟ 5 ΣΗΜΕΙΩΣΕΙΣ

Δομές Δεδομένων. Ενότητα 7: Άλλες παραλλαγές Συνδεδεμένων Λιστών-Παράσταση Αραιού Πολυωνύμου με Συνδεδεμένη Λίστα. Καθηγήτρια Μαρία Σατρατζέμη

Προγραμματισμός Υπολογιστών με C++ Φύλλο Διαγωνίσματος Ακαδημαϊκό εξάμηνο: Χειμερινό

ΒΑΣΙΚΟΙ ΤΥΠΟΙ ΚΑΙ ΠΙΝΑΚΕΣ

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

Η εντολή if-else. Η απλή μορφή της εντολής if είναι η ακόλουθη: if (συνθήκη) { Η γενική μορφή της εντολής ifelse. εντολή_1; εντολή_2;..

2 using namespace s t d ; 4 { 12 int t= x ; 6 x=y ; 7 y=t ; 8 } 9 11 { 13 x= y ; 14 y=t ; 15 } {

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

Δυναμική μνήμη με πίνακες και λίστες

Ελληνική Δημοκρατία Τεχνολογικό Εκπαιδευτικό Ίδρυμα Ηπείρου. Πληροφορική II. Ενότητα 2 : Αλγόριθμοι. Δρ. Γκόγκος Χρήστος

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

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

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

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

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

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

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

Μάθημα 21: Ουρές (Queues)

17TimeThis.h function returns reference pointer to same object { return *this; }

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

Εκφωνήσεις ασκήσεων εργαστηρίου 1

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

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

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

Transcript:

Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Σχολή Τεχνολογικών Εφαρμογών Ακαδημαϊκό έτος 2016-2017 ΤΕΙ Ηπείρου - Άρτα Δομές Δεδομένων και Αλγόριθμοι (εργαστήριο) Γκόγκος Χρήστος #3. Στατικές γραμμικές λίστες, συνδεδεμένες γραμμικές λίστες, γραμμικές λίστες της STL Γραμμικές λίστες Υπάρχουν δύο βασικοί τρόποι αναπαράστασης γραμμικών λιστών, η στατική αναπαράσταση η οποία γίνεται με τη χρήση πινάκων και η αναπαράσταση με συνδεδεμένη λίστα η οποία γίνεται με τη χρήση δεικτών. 1. Στατικές γραμμικές λίστες Στη στατική λίστα τα δεδομένα αποθηκεύονται σε πίνακα. Κάθε στοιχείο του πίνακα μπορεί να προσπελαστεί με βάση τη θέση του στον ίδιο σταθερό χρόνο με όλα τα άλλα στοιχεία άσχετα με τη θέση στην οποία βρίσκεται (τυχαία προσπέλαση). Ο κώδικας υλοποίησης μιας στατικής λίστας με μέγιστο αριθμό 50.000 στοιχείων παρουσιάζεται στη συνέχεια. #include <iostream> using namespace std; const int MAX = 50000; struct static_list { T elements[max]; int size = 0; ; T access(static_list<t>& static_list, int i) { if (i < 0 i >= static_list.size) throw -1; else return static_list.elements[i]; int search(static_list<t>& static_list, T x) { for (int i = 0; i < static_list.size; i++) if (static_list.elements[i] == x) return i; return -1; void push_back(static_list<t>& static_list, T x) { if (static_list.size == MAX) static_list.elements[static_list.size] = x; static_list.size++; void insert(static_list<t>& static_list, int i, T x) { if (static_list.size == MAX) if (i < 0 i >= static_list.size) [1]

for (int k = static_list.size; k > i; k--) { static_list.elements[k] = static_list.elements[k - 1]; static_list.elements[i] = x; static_list.size++; void delete_item(static_list<t>& static_list, int i) { if (i < 0 i >= static_list.size) for (int k = i; k < static_list.size; k++) { static_list.elements[k] = static_list.elements[k + 1]; static_list.size--; void print_list(static_list<t>& static_list) { cout << "List: "; for (int i = 0; i < static_list.size; i++) cout << static_list.elements[i] << " "; cout << endl; int main(int argc, char* argv[]){ static_list<int> alist; cout << "Add items 10, 20 and 30 to the list" << endl; push_back(alist, 10); push_back(alist, 20); push_back(alist, 30); print_list(alist); cout << "Item at position 2: " << access(alist, 2) << endl; cout << "Search for item 20: " << search(alist, 20) << endl; cout << "Insert at position 1 item 25" << endl; insert(alist,1,25); print_list(alist); cout << "Delete item at position 0" << endl; delete_item(alist, 0); print_list(alist); return 0; Add items 10, 20 and 30 to the list List: 10 20 30 Item at position 2: 30 Search for item 20: 1 Insert at position 1 item 25 List: 10 25 20 30 Delete item at position 0 List: 25 20 30 Στη συνέχεια παρουσιάζονται τα θετικά και τα αρνητικά σημεία της στατικής αναπαράστασης γραμμικής λίστας (Πίνακας 1). Θετικά Εύκολη υλοποίηση Σταθερός Ο(1) χρόνος εντοπισμού στοιχείου με βάση τη θέση του Γραμμικός χρόνος O(n) για αναζήτηση, εισαγωγή και διαγραφή στοιχείου Αρνητικά Δέσμευση μεγάλου τμήματος μνήμης ακόμη και όταν η λίστα περιέχει λίγα στοιχεία ή είναι άδεια Επιβάλει άνω όριο στο μέγεθος των δεδομένων που μπορεί να δεχθεί (ωστόσο ο περιορισμός αυτός μπορεί να ξεπεραστεί με συνθετότερη υλοποίηση που αυξομειώνει το μέγεθος του πίνακα υποδοχής όταν απαιτείται) Πίνακας 1. Πλεονεκτήματα και μειονεκτήματα της στατικής αναπαράστασης γραμμικής λίστας [2]

2. Συνδεδεμένες λίστες Η συνδεδεμένη λίστα αποτελείται από κανένα ή περισσότερους κόμβους. Κάθε κόμβος περιέχει δεδομένα και έναν ή περισσότερους δείκτες προς άλλους κόμβους της συνδεδεμένης λίστας. Κάποιοι από τους κόμβους μπορούν να δείχνουν στο NULL. Συχνά χρησιμοποιείται ένας πρόσθετος κόμβος με όνομα head (κόμβος κεφαλής) που δείχνει στο πρώτο στοιχείο της λίστας και μπορεί να περιέχει επιπλέον πληροφορίες για τη λίστα όπως το μήκος της. Η πρόσβαση στους κόμβους γίνεται ξεκινώντας από τον πρώτο κόμβο και διανύοντας την αλυσίδα των κόμβων μέσω των δεικτών μέχρι να βρεθεί ο κόμβος που αναζητείται. Ο κώδικας υλοποίησης μιας απλής συνδεδεμένης λίστας στοιχείων παρουσιάζεται στη συνέχεια. #include <iostream> using namespace std; struct node { T data; struct node<t>* next = NULL; ; struct linked_list { struct node<t>* head = NULL; int size = 0; ; struct node<t>* access(linked_list<t>& linked_list, int i) { if (i < 0 i >= linked_list.size) return NULL; struct node<t>* current = linked_list.head; for (int k = 0; k < i; k++) { current = current->next; return current; int search(linked_list<t>& linked_list, T x) { struct node<t>* current = linked_list.head; int i = 0; while (current!= NULL) { if (current->data == x) return i; current = current->next; return -1; void insert_after(linked_list<t>& linked_list, int i, T x) { if (i < 0 i >= linked_list.size) struct node<t>* ptr = access(linked_list, i); struct node<t>* new_node = new node<t>(); new_node->data = x; new_node->next = ptr->next; ptr->next = new_node; linked_list.size++; void insert_head(linked_list<t>& linked_list, T x) { struct node<t>* new_node = new node<t>(); new_node->data = x; new_node->next = linked_list.head; linked_list.head = new_node; linked_list.size++; [3]

void insert(linked_list<t>& linked_list, int i, T x) { if (i == 0) insert_head(linked_list, x); else insert_after(linked_list, i - 1, x); void push_back(linked_list<t>& l, T x) { struct node<t>* new_node, *current; new_node = new node<t>(); new_node->data = x; new_node->next = NULL; current = l.head; if (current == NULL) { l.head = new_node; l.size++; else { while (current->next!= NULL) { current = current->next; current->next = new_node; l.size++; void delete_item(linked_list<t>& l, int i) { if (i < 0 i >= l.size) if (i == 0) { struct node<t>* ptr = l.head; l.head = ptr->next; delete ptr; else { struct node<t>* ptr = access(l, i - 1); struct node<t>* to_be_deleted = ptr->next; ptr->next = to_be_deleted->next; delete to_be_deleted; l.size--; void print_list(linked_list<t>& l) { cout << "List: "; struct node<t>* current = l.head; while (current!= NULL) { cout << current->data << " "; current = current->next; cout << endl; int main(int argc, char* argv[]){ linked_list<int> alist; cout << "Add items 10, 20 and 30 to the list" << endl; push_back(alist, 10); push_back(alist, 20); push_back(alist, 30); print_list(alist); struct node<int>* x = access(alist, 2); cout << "Item at position 2: " << x->data << endl; cout << "Search for item 20: " << search(alist, 20) << endl; cout << "Insert at position 1 item 25" << endl; insert(alist,1,25); print_list(alist); cout << "Delete item at position 0" << endl; delete_item(alist, 0); print_list(alist); [4]

cout << "Insert item 5 at the start of the list" << endl; insert_head(alist, 5); print_list(alist); cout << "Insert item 201 after position 0" << endl; insert_after(alist,0,201); print_list(alist); return 0; Add items 10, 20 and 30 to the list List: 10 20 30 Item at position 2: 30 Search for item 20: 1 Insert at position 1 item 25 List: 10 25 20 30 Delete item at position 0 List: 25 20 30 Insert item 5 at the start of the list List: 5 25 20 30 Insert item 201 after position 0 List: 5 201 25 20 30 Στη συνέχεια παρουσιάζονται τα θετικά και τα αρνητικά σημεία της αναπαράστασης γραμμικής λίστα συνδεδεμένη λίστα (Πίνακας 2). με Θετικά Κάνει καλή χρήση του αποθηκευτικού χώρου Σταθερός χρόνος Ο(1) για την εισαγωγή και διαγραφή στοιχείων Αρνητικά Έχει συνθετότερη υλοποίηση Απαιτεί επιπλέον χώρο ανά στοιχείο λόγω της ύπαρξης των δεικτών Δεν επιτρέπει απευθείας μετάβαση σε κάποιο στοιχείο με βάση τον δείκτη του Πίνακας 2.. Πλεονεκτήματα και μειονεκτήματα της αναπαράστασης γραμμικής λίστας με συνδεδεμένη λίστα 3. Γραμμικές λίστες στην STL Στη C++ υπάρχει η υλοποίηση τόσο για τη στατική αναπαράσταση λίστας από την std::vector (διάνυσμα) όσο και για την αναπαράσταση συνδεδεμένης λίστας από την std::list (πρόκειται για διπλά συνδεδεμένη λίστα). 3.1 Η στατική γραμμική λίστα της STL std::vector<t> Στον κώδικα που ακολουθεί παρουσιάζεται η δημιουργία ενός διανύσματος ακεραίων και διάφορες λειτουργίες πάνω στο διάνυσμα όπως η εισαγωγή νέων στοιχείων σε συγκεκριμένες θέσεις του, η αναζήτηση στοιχείου, η διαγραφή στοιχείου η ταξινόμηση των στοιχείων του κ.α. #include <iostream> #include <vector> #include <algorithm> using namespace std; // using random access void print_std_vector(vector<int>& avector) { cout << "std::vector [ "; for (int i=0;i< avector.size();i++) cout << avector[i] << " "; cout << "]" << endl; // using range based for loop void print_std_vector2(vector<int>& avector) { cout << "std::vector [ "; for (int x : avector) cout << x << " "; cout << "]" << endl; [5]

// using iterator void print_std_vector3(vector<int>& avector) { cout << "std::vector [ "; for (vector<int>::iterator it=avector.begin();it!=avector.end();it++) cout << *it << " "; cout << "]" << endl; // using for_each and lambdas void print_std_vector4(vector<int>& avector) { cout << "std::vector [ "; for_each(avector.begin(), avector.end(), [](int x){cout << x << " ";); cout << "]" << endl; int main(int argc, char* argv[]){ cout << "Test for std::vector" << endl; cout << "add items 5,15,11" << endl; vector<int> avector = { 5, 15, 11 ; print_std_vector(avector); print_std_vector2(avector); print_std_vector3(avector); print_std_vector4(avector); vector<int>::iterator it = avector.begin(); advance(it, 1); cout << "value found at position 1 " << *it << endl; cout << "insert value 33 at position 1 " << endl; avector.insert(it, 33); print_std_vector(avector); cout << "insert value 44 at position 0 " << endl; it = avector.begin(); avector.insert(it, 44); print_std_vector(avector); cout << "search for item with value 33" << endl; it = find(avector.begin(), avector.end(), 33); cout << "value 33 found at position " << (it == avector.end()? -1 : std::distance(avector.begin(), it)) << endl; it = std::find(avector.begin(), avector.end(), 99); cout << "value 99 found at position " << (it == avector.end()? -1 : std::distance(avector.begin(), it)) << endl; cout << "delete item at position 2" << endl; it = avector.begin(); advance(it, 2); avector.erase(it); print_std_vector(avector); cout << "delete item at position 0" << endl; it = avector.begin(); avector.erase(it); print_std_vector(avector); cout << "sort items" << endl; sort(avector.begin(), avector.end()); print_std_vector(avector); return 0; Test for std::vector add items 5,15,11 std::vector [ 5 15 11 ] std::vector [ 5 15 11 ] std::vector [ 5 15 11 ] std::vector [ 5 15 11 ] value found at position 1 15 insert value 33 at position 1 std::vector [ 5 33 15 11 ] insert value 44 at position 0 std::vector [ 44 5 33 15 11 ] search for item with value 33 value 33 found at position 2 value 99 found at position -1 [6]

delete item at position 2 std::vector [ 44 5 15 11 ] delete item at position 0 std::vector [ 5 15 11 ] sort items std::vector [ 5 11 15 ] 3.2 H συνδεδεμένη γραμμική λίστα της STL std::list<t> Στον κώδικα που ακολουθεί παρουσιάζεται η δημιουργία μιας συνδεδεμένης λίστας ακεραίων καθώς και διάφορες λειτουργίες πάνω στη λίστα ανάλογες με τις λειτουργίες που παρουσιάστηκαν στη προηγούμενη παράγραφο για το διάνυσμα. #include <iostream> #include <list> #include <algorithm> using namespace std; // using range based for loop void print_std_list(list<int>& alist) { cout << "std::list [ "; for (int x : alist) cout << x << " "; cout << "]" << endl; // using iterator void print_std_list2(list<int>& alist) { cout << "std::list [ "; for (list<int>::iterator it=alist.begin();it!=alist.end();it++) cout << *it << " "; cout << "]" << endl; // using for_each and lambdas void print_std_list3(list<int>& alist) { cout << "std::list [ "; for_each(alist.begin(), alist.end(), [](int x){cout << x << " ";); cout << "]" << endl; int main(int argc, char* argv[]){ cout << "Test for std::list" << endl; cout << "add items 5,15,11" << endl; list<int> alist = { 5, 15, 11 ; print_std_list(alist); print_std_list2(alist); print_std_list3(alist); list<int>::iterator it = alist.begin(); advance(it, 1); cout << "value found at position 1 " << *it << endl; cout << "insert value 33 at position 1 " << endl; alist.insert(it, 33); print_std_list(alist); cout << "insert value 44 at position 0 " << endl; it = alist.begin(); alist.insert(it, 44); print_std_list(alist); cout << "search for item with value 33" << endl; it = find(alist.begin(), alist.end(), 33); cout << "value 33 found at position " << (it == alist.end()? -1 : std::distance(alist.begin(), it)) << endl; it = std::find(alist.begin(), alist.end(), 99); cout << "value 99 found at position " << (it == alist.end()? -1 : std::distance(alist.begin(), it)) << endl; cout << "delete item at position 2" << endl; [7]

it = alist.begin(); advance(it, 2); alist.erase(it); print_std_list(alist); cout << "delete item at position 0" << endl; it = alist.begin(); alist.erase(it); print_std_list(alist); cout << "sort items" << endl; alist.sort(); print_std_list(alist); return 0; Test for std::list add items 5,15,11 std::list [ 5 15 11 ] std::list [ 5 15 11 ] std::list [ 5 15 11 ] value found at position 1 15 insert value 33 at position 1 std::list [ 5 33 15 11 ] insert value 44 at position 0 std::list [ 44 5 33 15 11 ] search for item with value 33 value 33 found at position 2 value 99 found at position -1 delete item at position 2 std::list [ 44 5 15 11 ] delete item at position 0 std::list [ 5 15 11 ] sort items std::list [ 5 11 15 ] 4. Παράδειγμα χρήσης γραμμικών λιστών Έστω μια υποθετική τράπεζα η οποία έχει κάποιους πελάτες. Για κάθε πελάτη αποθηκεύονται μόνο το ονοματεπώνυμο και το υπόλοιπο του λογαριασμού του. Για τις ανάγκες του παραδείγματος θα δημιουργηθούν τυχαίοι πελάτες ως εξής: το όνομα κάθε πελάτη θα αποτελείται από 10 γράμματα που θα επιλέγονται με τυχαίο τρόπο από τα γράμματα της Αγγλικής αλφαβήτου και το δε υπόλοιπο κάθε πελάτη θα είναι ένας τυχαίος αριθμός από το 0 μέχρι το 5000. Θα παρουσιαστούν τέσσερις εκδόσεις του ίδιου προγράμματος. Η μεν πρώτη θα υλοποιείται με στατική λίστα, η δεύτερη με συνδεδεμένη λίστα η τρίτη με τη στατική γραμμική λίστα της C++, std::vector και η τέταρτη με τη συνδεδεμένη λίστα της C++, std::list. Και στις τέσσερις περιπτώσεις το πρόγραμμα θα πραγματοποιεί τις ακόλουθες λειτουργίες: 1. Θα δημιουργεί μια λίστα με 40000 τυχαίους πελάτες 2. Θα υπολογίζει το άθροισμα των υπολοίπων από όλους τους πελάτες που το όνομά τους ξεκινά με το χαρακτήρα Α 3. Θα προσθέτει για κάθε πελάτη που το όνομά του ξεκινά με το χαρακτήρα Α στην αμέσως επόμενη θέση έναν πελάτη με όνομα το αντίστροφο όνομα του πελάτη και το ίδιο υπόλοιπο λογαριασμού 4. Θα διαγράφει όλους τους πελάτες που το όνομά τους ξεκινά με το χαρακτήρα Β #include <iostream> #include <string> #include <random> #include <algorithm> [8]

#include <list> #include <chrono> using namespace std; using namespace std::chrono; mt19937 mt; uniform_int_distribution<int> uni1(0, 5000); uniform_int_distribution<int> uni2(0, 25); struct customer { string name; int balance; bool operator<(customer other) { return name < other.name; ; string generate_random_name(int k) { string name { ; string letters_en("abcdefghijklmnopqrstuvwxyz"); for (int j = 0; j < k; j++) { char c { letters_en[uni2(mt)] ; name += c; return name; /** * linear list (start) */ const int MAX = 50000; struct static_list { T elements[max]; int size = 0; ; T access(static_list<t>& static_list, int i) { if (i < 0 i >= static_list.size) throw -1; else return static_list.elements[i]; int search(static_list<t>& static_list, T x) { for (int i = 0; i < static_list.size; i++) if (static_list.elements[i] == x) return i; return -1; void push_back(static_list<t>& static_list, T x) { if (static_list.size == MAX) static_list.elements[static_list.size] = x; static_list.size++; void insert(static_list<t>& static_list, int i, T x) { if (static_list.size == MAX) if (i < 0 i >= static_list.size) for (int k = static_list.size; k > i; k--) { [9]

static_list.elements[k] = static_list.elements[k - 1]; static_list.elements[i] = x; static_list.size++; void delete_item(static_list<t>& static_list, int i) { if (i < 0 i >= static_list.size) for (int k = i; k < static_list.size; k++) { static_list.elements[k] = static_list.elements[k + 1]; static_list.size--; void print_customers_static_list(static_list<customer>& static_list, int k) { for (int i = 0; i < k; i++) { customer cu = access(static_list, i); cout << cu.name << " - " << cu.balance << endl; cout << "SIZE " << static_list.size << endl; void generate_data_static_list(static_list<customer>& static_list, int N) { for (int i = 0; i < N; i++) { customer c; c.name = generate_random_name(10); c.balance = uni1(mt); push_back(static_list, c); void total_balance_static_list(static_list<customer>& static_list, char c) { int sum = 0; for (int i = 0; i < static_list.size; i++) { customer cu = access(static_list, i); if (cu.name.at(0) == c) sum += cu.balance; cout << "Total balance for customers having name starting with character " << c << " is " << sum << endl; void add_extra_customers_static_list(static_list<customer>& static_list, char c) { int i = 0; while (i < static_list.size) { customer cu = access(static_list, i); if (cu.name.at(0) == c) { customer ncu; ncu.name = cu.name; reverse(ncu.name.begin(), ncu.name.end()); ncu.balance = cu.balance; insert(static_list, i + 1, ncu); void remove_customers_static_list(static_list<customer>& static_list, char c) { int i = 0; while (i < static_list.size) { customer cu = access(static_list, i); if (cu.name.at(0) == c) delete_item(static_list, i); else [10]

/** * linear list (end) */ /** * linked list (start) */ struct node { T data; struct node<t>* next = NULL; ; struct linked_list { struct node<t>* head = NULL; int size = 0; ; struct node<t>* access(linked_list<t>& linked_list, int i) { if (i < 0 i >= linked_list.size) return NULL; struct node<t>* current = linked_list.head; for (int k = 0; k < i; k++) { current = current->next; return current; int search(linked_list<t>& linked_list, T x) { struct node<t>* current = linked_list.head; int i = 0; while (current!= NULL) { if (current->data == x) return i; current = current->next; return -1; void insert_after(linked_list<t>& linked_list, int i, T x) { if (i < 0 i >= linked_list.size) struct node<t>* ptr = access(linked_list, i); struct node<t>* new_node = new node<t>(); new_node->data = x; new_node->next = ptr->next; ptr->next = new_node; linked_list.size++; void insert_head(linked_list<t>& linked_list, T x) { struct node<t>* new_node = new node<t>(); new_node->data = x; new_node->next = linked_list.head; linked_list.head = new_node; linked_list.size++; void insert(linked_list<t>& linked_list, int i, T x) { if (i == 0) insert_head(linked_list, x); [11]

else insert_after(linked_list, i - 1, x); void push_back(linked_list<t>& linked_list, T x) { struct node<t>* new_node, *current; new_node = new node<t>(); new_node->data = x; new_node->next = NULL; current = linked_list.head; if (current == NULL) { linked_list.head = new_node; linked_list.size++; else { while (current->next!= NULL) { current = current->next; current->next = new_node; linked_list.size++; void delete_item(linked_list<t>& linked_list, int i) { if (i < 0 i >= linked_list.size) if (i == 0) { struct node<t>* ptr = linked_list.head; linked_list.head = ptr->next; delete ptr; else { struct node<t>* ptr = access(linked_list, i - 1); struct node<t>* to_be_deleted = ptr->next; ptr->next = to_be_deleted->next; delete to_be_deleted; linked_list.size--; void print_linked_list(linked_list<t>& linked_list) { cout << "LINKED LIST: ["; struct node<t>* ptr; ptr = linked_list.head; int i = 0; while (ptr!= NULL) { cout << i << "-" << ptr->data << " "; ptr = ptr->next; cout << "]" << endl; void print_customers_linked_list(linked_list<customer>& linked_list, int k) { for (int i = 0; i < k; i++) { struct node<customer>* node = access(linked_list, i); customer cu = node->data; cout << cu.name << " - " << cu.balance << endl; cout << "SIZE " << linked_list.size << endl; void generate_data_linked_list(linked_list<customer>& linked_list, int N) { for (int i = 0; i < N; i++) { customer c; c.name = generate_random_name(10); c.balance = uni1(mt); push_back(linked_list, c); [12]

void total_balance_linked_list(linked_list<customer>& linked_list, char c) { struct node<customer>* ptr; ptr = linked_list.head; int i = 0; int sum = 0; while (ptr!= NULL) { customer cu = ptr->data; if (cu.name.at(0) == c) sum += cu.balance; ptr = ptr->next; cout << "Total balance for customers having name starting with character " << c << " is " << sum << endl; void add_extra_customers_linked_list(linked_list<customer>& linked_list, char c) { struct node<customer>* ptr; ptr = linked_list.head; while (ptr!= NULL) { customer cu = ptr->data; if (cu.name.at(0) == c) { customer ncu; ncu.name = cu.name; reverse(ncu.name.begin(), ncu.name.end()); ncu.balance = cu.balance; struct node<customer>* new_node = new node<customer>(); new_node->data = ncu; new_node->next = ptr->next; ptr->next = new_node; linked_list.size++; ptr = new_node->next; else ptr = ptr->next; void remove_customers_linked_list(linked_list<customer>& linked_list, char c) { struct node<customer>* ptr1; while (linked_list.size > 0) { customer cu = linked_list.head->data; if (cu.name.at(0) == c) { ptr1 = linked_list.head; linked_list.head = ptr1->next; delete ptr1; linked_list.size--; else break; if (linked_list.size == 0) ptr1 = linked_list.head; struct node<customer>* ptr2 = ptr1->next; while (ptr2!= NULL) { customer cu = ptr2->data; if (cu.name.at(0) == c) { ptr1->next = ptr2->next; delete (ptr2); ptr2 = ptr1->next; linked_list.size--; else { ptr1 = ptr2; ptr2 = ptr2->next; void remove_customers_linked_list_alt(linked_list<customer>& linked_list, char c) { int i = 0; [13]

while (i < linked_list.size) { struct node<customer>* current = access(linked_list, i); if (current->data.name.at(0) == c) delete_item(linked_list, i); else /** * linked list (end) */ /** * std::vector (start) */ void generate_data_stl_vector(vector<customer>& stl_vector, int N) { for (int i = 0; i < N; i++) { customer c; c.name = generate_random_name(10); c.balance = uni1(mt); stl_vector.push_back(c); void print_customers_stl_vector(vector<customer>& stl_vector, int k) { vector<customer>::iterator i; int c = 0; for (i = stl_vector.begin(); c < k && i!= stl_vector.end(); i++) { customer cu = *i; cout << cu.name << " - " << cu.balance << endl; c++; cout << "SIZE " << stl_vector.size() << endl; void total_balance_stl_vector(vector<customer>& stl_vector, char c) { vector<customer>::iterator i; int sum = 0; for (i = stl_vector.begin(); i!= stl_vector.end(); i++) { customer cu = *i; if (cu.name.at(0) == c) sum += cu.balance; cout << "Total balance for customers having name starting with character " << c << " is " << sum << endl; void add_extra_customers_stl_vector(vector<customer>& stl_vector, char c) { vector<customer>::iterator i = stl_vector.begin(); while (i!= stl_vector.end()) { customer cu = *i; if (cu.name.at(0) == c) { customer ncu; ncu.name = cu.name; reverse(ncu.name.begin(), ncu.name.end()); ncu.balance = cu.balance; stl_vector.insert(i, ncu); void remove_customers_stl_vector(vector<customer>& stl_vector, char c) { vector<customer>::iterator i = stl_vector.begin(); while (i!= stl_vector.end()) { [14]

customer cu = *i; if (cu.name.at(0) == c) { i = stl_vector.erase(i); else /** * std::vector (end) */ /** * std::list (start) */ void generate_data_stl_list(list<customer>& stl_list, int N) { for (int i = 0; i < N; i++) { customer c; c.name = generate_random_name(10); c.balance = uni1(mt); stl_list.push_back(c); void print_customers_stl_list(list<customer>& stl_list, int k) { list<customer>::iterator i; int c = 0; for (i = stl_list.begin(); c < k && i!= stl_list.end(); i++) { customer cu = *i; cout << cu.name << " - " << cu.balance << endl; c++; cout << "SIZE " << stl_list.size() << endl; void total_balance_stl_list(list<customer>& stl_list, char c) { list<customer>::iterator i; int sum = 0; for (i = stl_list.begin(); i!= stl_list.end(); i++) { customer cu = *i; if (cu.name.at(0) == c) sum += cu.balance; cout << "Total balance for customers having name starting with character " << c << " is " << sum << endl; void add_extra_customers_stl_list(list<customer>& stl_list, char c) { list<customer>::iterator i = stl_list.begin(); while (i!= stl_list.end()) { customer cu = *i; if (cu.name.at(0) == c) { customer ncu; ncu.name = cu.name; reverse(ncu.name.begin(), ncu.name.end()); ncu.balance = cu.balance; stl_list.insert(i, ncu); else void remove_customers_stl_list(list<customer>& stl_list, char c) { list<customer>::iterator i = stl_list.begin(); while (i!= stl_list.end()) { customer cu = *i; [15]

if (cu.name.at(0) == c) { i = stl_list.erase(i); else /** * std::list (end) */ void test_static_list() { mt = *(new mt19937(1940)); cout << "Testing static list" << endl; cout << "########################################################" << endl; high_resolution_clock::time_point struct static_list<customer> static_list; generate_data_static_list(static_list, 40000); high_resolution_clock::time_point print_customers_static_list(static_list, 5); auto std::chrono::duration_cast<std::chrono:: microseconds>( t2 - t1).count(); total_balance_static_list(static_list, 'A'); add_extra_customers_static_list(static_list, 'A'); print_customers_static_list(static_list, 5); remove_customers_static_list(static_list, 'B'); print_customers_static_list(static_list, 5); cout << "########################################################" << endl; void test_linked_list() { mt = *(new mt19937(1940)); cout << "Testing linked list" << endl; cout << "########################################################" << endl; struct linked_list<customer> linked_list; high_resolution_clock::time_point generate_data_linked_list(linked_list, 40000); high_resolution_clock::time_point print_customers_linked_list(linked_list, 5); auto std::chrono::duration_cast<std::chrono:: microseconds>( t2 - t1).count(); total_balance_linked_list(linked_list, 'A'); [16]

add_extra_customers_linked_list(linked_list, 'A'); print_customers_linked_list(linked_list, 5); remove_customers_linked_list(linked_list, 'B'); // remove_customers_linked_list_alt(linked_list, 'B'); print_customers_linked_list(linked_list, 5); cout << "########################################################" << endl; void test_stl_vector() { mt = *(new mt19937(1940)); cout << "Testing stl vector" << endl; cout << "########################################################" << endl; high_resolution_clock::time_point vector<customer> stl_vector; generate_data_stl_vector(stl_vector, 40000); high_resolution_clock::time_point print_customers_stl_vector(stl_vector, 5); auto std::chrono::duration_cast<std::chrono:: microseconds>( t2 - t1).count(); total_balance_stl_vector(stl_vector, 'A'); add_extra_customers_stl_vector(stl_vector, 'A'); print_customers_stl_vector(stl_vector, 5); remove_customers_stl_vector(stl_vector, 'B'); print_customers_stl_vector(stl_vector, 5); cout << "########################################################" << endl; void test_stl_list() { mt = *(new mt19937(1940)); cout << "Testing stl list" << endl; cout << "########################################################" << endl; high_resolution_clock::time_point list<customer> stl_list; generate_data_stl_list(stl_list, 40000); high_resolution_clock::time_point print_customers_stl_list(stl_list, 5); auto std::chrono::duration_cast<std::chrono:: microseconds>( t2 - t1).count(); total_balance_stl_list(stl_list, 'A'); [17]

add_extra_customers_stl_list(stl_list, 'A'); print_customers_stl_list(stl_list, 5); remove_customers_stl_list(stl_list, 'B'); print_customers_stl_list(stl_list, 5); cout << "########################################################" << endl; int main(int argc, char **argv) { test_static_list(); test_linked_list(); test_stl_vector(); test_stl_list(); Testing static list ######################################################## SIZE 40000 Time elapsed: 55003 microseconds Total balance for customers having name starting with character A is 3871562 Time elapsed: 6000 microseconds SIZE 41552 Time elapsed: 624036 microseconds SIZE 39921 Time elapsed: 680039 microseconds ######################################################## Testing linked list ######################################################## SIZE 40000 Time elapsed: 2805161 microseconds Total balance for customers having name starting with character A is 3871562 Time elapsed: 7001 microseconds [18]

SIZE 41552 Time elapsed: 6000 microseconds SIZE 39921 Time elapsed: 6001 microseconds ######################################################## Testing stl vector ######################################################## SIZE 40000 Time elapsed: 55003 microseconds Total balance for customers having name starting with character A is 3871562 Time elapsed: 7001 microseconds SIZE 41552 Time elapsed: 484027 microseconds SIZE 39921 Time elapsed: 480027 microseconds ######################################################## Testing stl list ######################################################## SIZE 40000 Time elapsed: 57004 microseconds Total balance for customers having name starting with character A is 3871562 Time elapsed: 6001 microseconds SIZE 41552 Time elapsed: 6000 microseconds [19]

SIZE 39921 Time elapsed: 6001 microseconds ######################################################## Η εκτέλεση καθεμιάς από τις τέσσερις λειτουργίες χρονομετρείται με ακρίβεια microsecond για κάθε περίπτωση λίστας ξεχωριστά και τα αποτελέσματα παρουσιάζονται σε γράφημα. Λόγω του ότι υπάρχουν διαφορές κλίμακας στο χρόνο εκτέλεσης ο άξονας y του γραφήματος είναι λογαριθμικός. Λειτουργία 1 Λειτουργία 2 Λειτουργία 3 Λειτουργία 4 Στατική λίστα 55003 6000 624036 680039 Συνδεδεμένη λίστα 2805161 7001 6000 6000 Λίστα std::vector 55003 7001 484027 480027 Λίστα std::list 57004 6001 6000 6001 Απόδοση λειτουργιών ανά είδος γραμμικής λίστας 10000000 1000000 100000 10000 1000 Λίστα std::list Λίστα std::vector Συνδεδεμένη λίστα Λειτουργία 1 Λειτουργία 2 Λειτουργία 3 Στατική λίστα Λειτουργία 4 Στατική λίστα Συνδεδεμένη λίστα Λίστα std::vector Λίστα std::list Χρήσιμοι σύνδεσμοι http://cplus.about.com/od/learning1/ss/pointers.htm#step1 http://www.algorithmist.com/index.php/linked_list http://www.geeksforgeeks.org/data-structures/#linkedlist http://visualgo.net/list.html [20]