Presentation is loading. Please wait.

Presentation is loading. Please wait.

More STL Container Classes ECE 297. 2 Last Time Templates –Functions –Classes template void swap_val (VariableType &a, VariableType &b) { VariableType.

Similar presentations


Presentation on theme: "More STL Container Classes ECE 297. 2 Last Time Templates –Functions –Classes template void swap_val (VariableType &a, VariableType &b) { VariableType."— Presentation transcript:

1 More STL Container Classes ECE 297

2 2 Last Time Templates –Functions –Classes template void swap_val (VariableType &a, VariableType &b) { VariableType temp; temp = a; a = b; b = temp; } int main() { int a = 1; int b = 2; swap_val(a, b); }

3 3 Last Time Standard Template Library (STL) –Algorithms: min(), max() –Container Classes: Vector #include using namespace std; vector get_input ( ) { vector vec; // vector of ints, initially empty int val; cin >> val; while ( !cin.fail() ) { vec.push_back (val); // Add new value to end of vector cin >> val; } return (vec); // Return the whole vector }

4 4 Today Iterators –Perform advanced operations on Containers Find Insert Remove More Container Classes –List: Doubly Linked List –Map: Binary Search Tree

5 Removing Elements From Containers

6 6 Erasing Elements Remove negative values from argument –Return negative values in another vector #include using namespace std; vector extract_negatives (vector & numbers) { return negatives; } 1, 4, -6, 3, -8, -10 numbers 1, 4, 3 numbers -6, -8, -10 negatives

7 7 Erasing Elements Remove negative values from argument –Return negative values in another vector #include using namespace std; vector extract_negatives (vector & numbers) { vector negatives; int i = 0; while(i < numbers.size()) { if(numbers[i] < 0) { negatives.push_back(numbers[i]); numbers.erase(numbers.begin() + i); } else { i++; //Next element } } return negatives; } Remove the i th element

8 8 What is going on? processed elementsNEGunprocessed elements numbers.size() = n element i processed elementsunprocessed elements numbers.size() = n - 1 elements copied numbers.erase(numbers.begin() + i); Denotes first element (index 0) i elements after

9 9 Using Extract Negatives #include using namespace std; int main() { vector values = {1, 4, -6, 3, -8, -10}; vector negatives = extract_negatives(values); cout << “Positives: “; for(int i = 0; i < values.size(); i++) cout << values[i] << “ “; cout << endl; cout << “Negatives: “; for(int i = 0; i < negatives.size(); i++) cout << negatives[i] << “ “; cout << endl; return 0; } Output: Positives: 1, 4, 3 Output: Negatives: -6, -8, -10

10 Iterators

11 11 Iterators numbers[i] –Implies random access –Not supported by all data structures (e.g. Linked Lists) An iterator is an object that: –Identifies an element –Allows us to access the element –Allows us to move between elements –Is restricted to efficient operations numbers.size() = n numbers.begin() … 0 12345n - 1 numbers.end() Note: one past the end!

12 12 Vector Iterators vs Indices Using indices Using Iterators for(int i = 0; i < negatives.size(); i++) { cout << negatives[i] << endl; } for(vector ::iterator iter = negatives.begin(); iter != negatives.end(); iter++) { cout << *iter << endl; } Type of iterator Dereference (*) to get element value Explicit check for end value Initialize to start Advance to next element Pointers are (random-access) iterators

13 13 Iterator Operations vector numbers = {1, 2, 3, 4}; vector ::iterator iter = numbers.begin(); iter = 5; iter++; iter--; int x = *iter; iter != numbers.end(); iter < numbers.end(); *iter = 27; iter = numbers.begin() + i; container-type::iterator –E.g. vector ::iterator //No! Can’t set iterator to arbitrary value //Yes, set value of element //Yes, advance to next element //Yes, get value of element //Yes, point to start of container //Yes, for random access (e.g. vector) iterators class name iterator is a type defined inside this class  proper kind of iterator for this class //Yes, go to prior element //Yes, (for random access iterators), point to element i //Yes, == and != defined

14 14 Iterator Types vector numbers = {1, 2, 3, 4}; vector ::const_iterator c_iter = numbers.begin(); c_iter++; int x = *c_iter; int x2 = *(c_iter + 2) *c_iter = 27; container-type::iterator –E.g. vector ::iterator –Read-write access to elements –Can make changes to container container-type::const_iterator –E.g. vector ::const_iterator –Read-only access to elements –Can not make changes //No! Const iterator can’t change element value //Yes, advance to next element //Yes, get value of element //OK Like float *p; vs. const float *p ; //Yes, (for random access iterators)

15 15 Extract Negative with Iterators #include using namespace std; vector extract_negatives (vector & numbers) { vector negatives; int i = 0; //change this to use iterator instead of index while(i < numbers.size()) { //and this if(numbers[i] < 0) { //and this negatives.push_back(numbers[i]); //and this numbers.erase(numbers.begin() + i); //and this } else { i++; //Next element //and this } return negatives; }

16 16 Extract Negative with Iterators #include using namespace std; vector extract_negatives (vector & numbers) { vector negatives; vector ::iterator iter = numbers.begin(); while(iter != numbers.end()) { if(*iter < 0) { negatives.push_back(*iter); iter = numbers.erase(iter); //Returns next iter } else { iter++; //Next element } return negatives; } numbers.erase(iter) invalidates iter –Returns an iterator for the next element

17 17 What about performance? processed elementsNEGunprocessed elements numbers.size() = n iter processed elementsunprocessed elements numbers.size() = n - 1 elements copied numbers.erase(iter); What if: vector numbers = {-1, -2, -3, -4, -5, -6, …}; Slow: –Erase is expensive with a vector: O(n) –Therefore extract_negatives() is O(n 2 )

18 18 What about performance? processed elementsNEGunprocessed elements numbers.size() = n iter processed elementsunprocessed elements numbers.size() = n - 1 elements copied numbers.erase(iter); What if: vector numbers = {-1, -2, -3, -4, -5, -6, …}; Slow: –Erase is expensive with a vector: O(n) –Therefore extract_negatives() is O(n 2 ) Data 0 Data 1 Data 2 Data 3 Data 4 Data 5 Data 6 Data 7 Data 8 Data 9

19 19 What about performance? processed elementsNEGunprocessed elements numbers.size() = n iter processed elementsunprocessed elements numbers.size() = n - 1 elements copied numbers.erase(iter); What if: vector numbers = {-1, -2, -3, -4, -5, -6, …}; Slow: –Erase is expensive with a vector: O(n) –Therefore extract_negatives() is O(n 2 ) Data 0 Data 1 Data 2 Data 3 Data 4 Data 5 Data 6 Data 7 Data 8 Data 9

20 20 What about performance? processed elementsNEGunprocessed elements numbers.size() = n iter processed elementsunprocessed elements numbers.size() = n - 1 elements copied numbers.erase(iter); What if: vector numbers = {-1, -2, -3, -4, -5, -6, …}; Slow: –Erase is expensive with a vector: O(n) –Therefore extract_negatives() is O(n 2 ) Data 0 Data 1 Data 3 Data 4 Data 5 Data 6 Data 7 Data 8 Data 9

21 List

22 22 Doubly Linked List Bi-directional Access –Can move forward and back –No random access: iter + 5 Fast insert and erase –Only need to update neighbours: O(1) STL – Data Head Tail iter++; iter--;

23 23 Extract Negatives with #include using namespace std; list extract_negatives (list & numbers) { list negatives; list ::iterator iter = numbers.begin(); while(iter != numbers.end()) { if(*iter < 0) { negatives.push_back(*iter); iter = numbers.erase(iter); //Returns next iter } else { iter++; //Next element } return negatives; } Only had to change types! –Now extract_negatives() is O(n)

24 24 Adding Elements to a List #include using namespace std; int main() { list values; values.push_back(5); values.push_back(-2); values.push_front(1); values.push_front(-7); for(list ::const_iterator iter = values.begin(); iter != values.end(); iter++) { cout << *iter << “ “; } cout << endl; return 0; } Output: -7 1 5 -2 //Append to last //Prepend to start

25 25 Inserting Elements in a List #include using namespace std; int main() { list values = {1, 2, 3, 4}; list ::iterator iter = values.begin(); // Value: 1 iter++; // Value: 2 iter++; // Value: 3 values.insert(iter, 0); //Inserts value 0 before iter for(list ::const_iterator iter = values.begin(); iter != values.end(); iter++) { cout << *iter << “ “; } cout << endl; return 0; } Output: 1, 2, 0, 3, 4

26 26 Simplifying Iterator Types with ‘auto’ Normal vector negatives = {-1, -2, -3, -4}; for(auto iter = negatives.begin(); iter != negatives.end(); iter++) { cout << *iter << endl; } vector negatives = {-1, -2, -3, -4}; for(vector ::iterator iter = negatives.begin(); iter != negatives.end(); iter++) { cout << *iter << endl; } Using Auto –Compiler knows negatives.begin() returns vector ::iterator

27 STL Algorithms with Iterators

28 28 Finding Elements by Value #include using namespace std; int main() { list items = {1, 2, 3, 4}; list ::iterator iter = find(items.begin(), items.end(), 3); if(iter != items.end()) cout << “Found ” << *iter << endl; iter = find(items.begin(), items.end(), 42); if(iter == items.end()) cout << “Could not find 42” << endl; return 0; } Output: Found 3 Could not find 42 Look in entire list Like checking for a NULL pointer

29 29 Finding Max Value in Sequence #include using namespace std; int main() { vector values = {1, 2, 3, 4}; auto max_val = max_element(values.begin(), values.end()); cout << “Largest value is “ << *max_val << endl; return 0; } Output: Largest value is 4

30 30 Sorting Vectors #include using namespace std; int main() { vector values = {5, 8, 2, 4, 1, 9, 12}; sort(values.begin(), values.end()); for(vector ::const_iterator iter = values.begin(); iter != values.end(); iter++) { cout << *iter << “ “; } cout << endl; return 0; } Output: 1, 2, 4, 5, 8, 9, 12 Container must support random-access iterators

31 31 Sorting Comparison sort(values.begin(), values.end()); How does sort() compare values? –By default operator< of values in container Can provide your own comparison function –E.g. sort in descending order #include #include //For greater<>() sort(values.begin(), values.end(), greater ());

32 32 Sorting Lists #include using namespace std; int main() { list values = {5, 8, 2, 4, 1, 9, 12}; values.sort(); for(list ::const_iterator iter = values.begin(); iter != values.end(); iter++) { cout << *iter << “ “; } cout << endl; return 0; } Output: 1, 2, 4, 5, 8, 9, 12 No random-access, must use member function

33 33 Iterator Categories Forward –Example: Singly Linked List Bi-Directional –Example: Random Access –Example: iter++; iter--; iter++; iter--; iter + n;

34 Associative Containers

35 35 Associative Containers How can we find a value in a vector? – find() –Order container, search efficiently Difficult, error prone Alternative: Associative Container –Container handles ordering elements for efficient look-up –Use a key to look-up values –Example: Maps keys values O(n)

36 36 Map Typically a Binary Search Tree (BST) –Self-balancing –Guaranteed: O(logn) find insert erase Uses std::pair –First: key –Second: value ECE244 Lab 5: Domain Name Lookup –Look-up domain name to get IP Address “www.google.com” 2915183441 5 1 3 6 9 pair google(“www.google.com”, 2915183441);

37 37 Map Insertion #include using namespace std; int main() { map dns_lookup; pair google(“www.google.com”, 215183441); dns_lookup.insert(google); pair apple = make_pair(“www.apple.com”, 398782126); dns_lookup.insert(apple); //Using make_pair() to avoid specifying template parameters dns_lookup.insert(make_pair("www.utoronto.ca", 918567265)); return 0; }

38 38 Map Look-up #include using namespace std; int main() { map dns_lookup; dns_lookup.insert(make_pair(“www.google.com”, 215183441)); dns_lookup.insert(make_pair(“www.apple.com”, 398782126)); dns_lookup.insert(make_pair("www.utoronto.ca”, 918567265 )); map ::iterator iter1 = dns_lookup.find(“www.apple.com"); if(iter1 != dns_lookup.end()) { cout second << endl; } auto iter2 = dns_lookup.find(“www.microsoft.com"); if(iter2 == dns_lookup.end()) { cout << “Did not find www.microsoft.com” << endl; } return 0; } Output: www.apple.com: 398782126 Did not find www.microsoft.com key value only key keyvalue

39 39 Map Removal & Iteration #include using namespace std; int main() { map dns_lookup; dns_lookup.insert(make_pair(“www.google.com”, 215183441)); dns_lookup.insert(make_pair(“www.apple.com”, 398782126)); dns_lookup.insert(make_pair("www.utoronto.ca”, 918567265 )); dns_lookup.erase(“www.utoronto.ca”); //Remove by key for(map ::iterator iter = dns_lookup.begin(); iter != dns_lookup.end(); iter++) { cout first second << endl; } return 0; } Output: www.apple.com: 398782126 www.google.com: 215183441 Iteration ordered by keys  In-order traversal

40 40 Alternative Map Syntax #include using namespace std; int main() { map dns_lookup; dns_lookup[“www.google.com”] = 215183441; //Insert dns_lookup[“www.apple.com”] = 398782126; cout << “Google: “ << dns_lookup[“www.google.com”] << endl; cout << “Microsoft: “ << dns_lookup[“www.microsoft.com”] << endl; for(auto iter = dns_lookup.begin(); iter != dns_lookup.end(); iter++) { cout first second << endl; } return 0; } Output: Google: 215183441 Microsoft: 0 www.apple.com: 398782126 www.google.com: 215183441 www.microsoft.com: 0 Unintentional Insertion! key value key, returns value

41 41 Repeated Elements? #include using namespace std; int main () { map salary_db; // key: name; value: salary salary_db.insert (make_pair("Bob Smith", 90000)); salary_db.insert (make_pair(“Linda Strong", 70000)); salary_db.insert (make_pair("Bob Smith", 15000)); auto emp = salary_db.find ("Bob Smith"); cout first second << endl; } Output: Bob Smith earns $90000 Duplicate entry: not inserted

42 42 Repeated Elements? Multimap #include using namespace std; int main () { multimap salary_db; // key: name; value: salary salary_db.insert (make_pair("Bob Smith", 90000)); salary_db.insert (make_pair(“Linda Strong", 70000)); salary_db.insert (make_pair("Bob Smith", 15000)); auto emp = salary_db.find ("Bob Smith"); cout first second << endl; } Output: Bob Smith earns $90000 or Bob Smith earns $15000 One of the duplicates returned (randomly)

43 43 Repeated Elements? #include using namespace std; int main () { multimap salary_db; // key: name; value: salary salary_db.insert (make_pair("Bob Smith", 90000)); salary_db.insert (make_pair(“Linda Strong", 70000)); salary_db.insert (make_pair("Bob Smith", 15000)); auto range = salary_db.equal_range("Bob Smith"); for (auto iter = range.first; iter != range.second; iter++) cout first second << endl; } Output: Bob Smith earns $90000 Bob Smith earns $15000 Returns pair giving the range of matching entries [first, second)

44 Additional Container Classes

45 45 Unordered Map std::unordered_map –Typically a Hash Table –On Average: find insert erase –Grows automatically Same interface as –Except: Iteration not ordered Order may change after insertion/deletion Never fills up and slows down! O(1)

46 46 Queues std::queue –First-In First-Out (FIFO) Order std::priority_queue –Queue ordered by value –First element is largest value

47 47 Stack std::stack –Last-In First-Out (LIFO) Order push pop

48 48 Set, –A collection of objects –Similar to with only keys (no values) std::set –Set where elements are ordered std::unordered_set –Set where elements are unordered

49 49 Deque –Double-ended queue std::deque –Similar to but also efficient: push_front() pop_front()

50 50 Wow, That’s a Lot of Classes & Functions! Big menu but you don’t have to eat it all! This course: pick which data structures you need  STL can help you build them quickly


Download ppt "More STL Container Classes ECE 297. 2 Last Time Templates –Functions –Classes template void swap_val (VariableType &a, VariableType &b) { VariableType."

Similar presentations


Ads by Google