Τμήμα Μηχανικών Πληροφορικής Τ.Ε. Σχολή Τεχνολογικών Εφαρμογών Ακαδημαϊκό έτος 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]