Download presentation
Presentation is loading. Please wait.
1
Overloaded Function (P.311)
Recall “function overloading” on P.311 We have three functions with the same name: int max(int x[], int len); long max(long x[], int len); double max(double x[], int len); The code is essentially the same for each function, but with different parameter types.
2
Function Templates (P.314)
C++ compiler can automatically generate functions with various parameter types. The functions generated by a function template all have the same basic code, but customized by the type arguments that you supply.
3
Function Templates (P.314)
type parameter template <class T> T max (T x[], int len) { T maximum(x[0]); for (int i = 1; i < len; i++) if (maximum < x[i]) maximum = x[i]; return maximum; }
4
T is replaced by a specific type argument, such as “long”
Instantiation T is replaced by a specific type argument, such as “long” long max (long x[], int len) { long maximum(x[0]); for (int i = 1; i < len; i++) if (maximum < x[i]) maximum = x[i]; return maximum; }
5
Ex6_08.cpp (P.315) #include <iostream> using std::cout; using std::endl; // Template for function to compute the maximum element of an array template<typename T> T max(T x[], int len) { T maximum(x[0]); for(int i = 1; i < len; i++) if(maximum < x[i]) maximum = x[i]; return maximum; }
6
Ex6_08.cpp (cont.) int main(void) { int small[] = { 1, 24, 34, 22}; long medium[] = { 23, 245, 123, 1, 234, 2345}; double large[] = { 23.0, 1.4, 2.456, 345.5, 12.0, 21.0}; int lensmall(sizeof small/sizeof small[0]); int lenmedium(sizeof medium/sizeof medium[0]); int lenlarge(sizeof large/sizeof large[0]); cout << endl << max(small, lensmall); cout << endl << max(medium, lenmedium); cout << endl << max(large, lenlarge); cout << endl; return 0; }
7
Class Templates (P.477)
8
Chapter 10 Standard Template Library (STL)
9
The Standard Template Library (P.645)
The STL is a large collection of class templates and function templates provided with your native C++ compiler. STL provides class templates that relieves you of the trouble of memory management. In the class of Data Structure, you will learn how to implement these by yourselves: vector, list, hash, set, queue, stack
10
Some useful STL class templates
vector an array that can increase in capacity automatically when required. You can only add new elements efficiently to the end of a vector. deque Double-ended queue Equivalent to a vector but you can add elements to the beginning efficiently. list a doubly-linked list
11
Figure 10-2 (P.652)
12
Creating Vector Containers
Containers (P.646) are objects that you use to store and organize other objects. an int vector – an array of integers a string list – a list of strings Instead of defining CInt_Vector, CFloat_Vector, CString_Vector, you have a class template vector<T>. Creating vector<T> containers: vector<string> strings; vector <double> data; vector <int> mydata;
13
Visual C++ implements this as a 4-byte unsigned integer
A Simple Example #include <iostream> #include <vector> using std::cout; using std::endl; using std::vector; int main() { vector<int> mydata; mydata.push_back(98); mydata.push_back(99); mydata.push_back(100); for (size_t i=0; i<mydata.size(); i++) cout << mydata[i] << ' '; cout << endl; return 0; } Visual C++ implements this as a 4-byte unsigned integer
14
Create a Vector vector<int> mydata; mydata.push_back(99);
If you add new elements to this vector, the memory allocated for the vector will be increased automatically. vector<int> mydata(100); Create a vector that contains 100 elements that are all initialized to zero. vector<int> mydata(100, -1); Create a vector that contains 100 elements that are all initialized to -1.
15
Create a Vector (cont.) Create a vector with initial values for elements from an external array. int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; vector<int> mydata(data, data+8); // mydata will contain You may also specify it as vector<int> mydata(data.begin(), data.end()); A sequence of elements is specified in the STL by two iterators (image iterators as something like pointers, P.648): one pointing to the first element in the sequence the other pointing to one past the last element in the sequence
16
Iterator Iterate over all the elements in the sequence by incrementing the begin iterator until it equals the end iterator. Suppose mydata contains vector<double> values(mydata.begin()+2, mydata.end()-1) // values will contain Note the end iterator points to one past the last element. Reverse iterator: rbegin() and rend().
17
Capacity and Size of a Vector Container
capacity() – the maximum number of objects a container can currently accommodate. size() – the number of objects stored in the container. empty() – Boolean function which tests whether size() is 0. Both values are returned as type vector<T>::size_type In Visual C++, this is implemented as size_t, a 4-byte unsigned integer.
18
Resize a Vector vector<int> values(5, 66); // 66 66 66 66 66
values.resize(7,88); // values.resize(10); // // If you don’t specify a value for new elements, // the default value of the object will be produced. values.resize(4); //
19
Ex10_01.cpp (P.657) Observe how the capacity grows.
listInfo(vector<T> &v) pass-by-reference runs faster if the vector is very large Output the elements with the loop You may also use the auto keyword for (auto i = 0; i<numbers.size(); i++) cout << “ “ << numbers[i]; Or using an iterator for (vector<int>::iterator iter = numbers.begin(); iter < numbers.end(); iter++) cout << “ “ << *iter; Observe how the capacity grows.
20
Accessing Elements in a Vector
Use the subscript operator, just like an array cout << numbers[i]; Use the at() function where the argument is the index position. cout << numbers.at(i);
21
Inserting and Deleting Elements in a Vector
push_back(); pop_back(); clear(); the size will be 0; the capacity will be left unchanged. insert(); erase(); Both the erase() and insert() operations are slow.
22
Storing Objects in a Vector
Person.h (P.664) A class defining people by their name showPerson() initName() is invoked by Constructor Copy constructor Assignment operator Ex10_02.cpp
23
Sorting Vector Elements
sort(data, data+count); Note the pointer marking the end of the sequence of elements must be one past the last element. sort(data, data+count, greater<int>()); Sorting in descending order. Remember to “using std::greater”
24
Exercises Modify Ex10_02.cpp, so that after the input names are printed out, print a separator consisting of dashes (-), whose total length is the same as the longest name, and then print out all names in sorted ascending order. Redefine the operator< in Person.h, so that when we compare two names, the longer one is regarded as larger (e.g. “Yankee” < “Elizabeth”). If two names have the same length, then compare their alphabetic order.
25
Double-Ended Queue deque<T> - the double-ended queue container template It is similar to a vector. It can do everything a vector container can. It includes the same function members. But you can add and delete elements efficiently at the beginning as well as at the end. push_front() pop_front()
26
Ex10_04.cpp (P.672) Create the container and two iterator variables:
deque<int> data; deque<int>::iterator iter; deque<int>::reverse_iterator riter; while (cin >> value, value !=0) separating two expressions with the comma operator. The value of a series of expressions separated by commas is the value of the rightmost expression. (P.??) (P.75)
27
Ex10_04.cpp (cont.) Use iter as the loop control variable to output the values. The loop ends when iter is incremented to be equal to the iterator returned by the end() function. iter = data.begin(); while (iter != data.end()) cout << *iter++ << “ “; Use a reverse iterator riter to output the values in reverse order for (riter = data.rbegin() ; riter != data.rend(); riter++) cout << *riter << “ “;
28
Accumulate() Algorithm
accumulate(data.begin(), data.end(), 0) Although you could use a conventional loop to do this, you may make use of the accumulate() algorithm (defined in the numeric header) to calculate the sum. The first two arguments specify the iterators defining the sequence of elements. The third argument specifies an initial value for the sum (which is generally 0).
29
Sorting a Double-Ended Queue
The default operation of the sort() algorithm is to sort the sequence in ascending order. sort (data.begin(), data.end() ); sort (data.rbegin(), data.rend() ); Pass reverse iterators to sort() will make it see the elements in reverse order, and sorts the sequence in descending order. Let’s have an exercise on Bubble Sort.
30
Bubble Sort Compare 2 to 7; 2 is smaller than 7 so swap them 9 5 7 2
31
Bubble Sort 9 9 5 5 7 2 2 7 Compare 2 to 5;
2 is smaller than 5 so swap them 9 9 5 5 7 2 2 7
32
Bubble Sort 9 9 9 5 5 2 7 2 5 2 7 7 Compare 2 to 9;
2 is smaller than 9 so swap them 9 9 9 5 5 2 7 2 5 2 7 7
33
After the first round you see 2 (the smallest element) is on the top
Bubble Sort 9 9 9 2 5 5 2 9 7 2 5 5 2 7 7 7
34
Bubble Sort 2 9 5 7 Compare 5 to 7;
5 is smaller than 7 so leave them alone 2 9 5 7
35
Bubble Sort 2 2 9 9 5 5 7 7 Compare 9 to 5;
9 is greater than 5 so swap them 2 2 9 9 5 5 7 7
36
Bubble Sort 2 2 2 9 9 5 After the 2nd round, the 2nd smallest element (5) also rises to the correct position. 5 5 9 7 7 7
37
Bubble Sort Compare 9 to 7; 9 is greater than 7 so swap them 2 5 9 7
38
Bubble Sort At the end of the 3rd round, the sequence is sorted in ascending order. 2 2 5 5 9 7 7 9
39
Exercise: Bubble Sort on deque<T>
Define your own class myQueue. Create a member function bsort(). The function takes two arguments which are iterators specifying the sequence of elements to be sorted. The function will print out the sequence during the sorting process. For example 0: [ ] (before sorting) 1: [ ] 2: [ ] 3: [ ] (after sorting)
40
Performance Consideration
Because of the additional capability it offers, the memory management for a double-ended queue is more complicated than for a vector, so it will be slightly slower. (P.672) Let’s try to measure how “slower” it is.
41
Measure the running time of a program
#include <iostream> #include <time.h> using std::cout; using std::endl; int main() { const int K = 10000; clock_t t0, t1; t0 = clock(); for (int i=0; i<K; i++) for (int j=0; j<K; j++); t1 = clock(); cout << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << endl; cout << t0 << '\t' << t1 << endl; cout << static_cast<float>(t1 - t0) / CLOCKS_PER_SEC << endl; return 0; }
42
time() You may also get the current time (wall-clock time):
#include <iostream> #include <time.h> using std::cout; using std::endl; int main() { time_t t0; cout << "Seconds elapsed since " << "0 hours, 0 minutes, 0 seconds, January 1, 1970: " << time(&t0) << endl; return 0; } Seconds elapsed since 0 hours, 0 minutes, 0 seconds, January 1, 1970:
43
Interpret the Output of time()
Seconds elapsed since 0 hours, 0 minutes, 0 seconds, January 1, 1970: = … 20464 20464 3600 = 5 … 2464 2464 60 = 41 … 4 Current time (HH:MM:SS) is 05:41:04 GTM (Greenwich Mean Time) + 8 = TWN So the local time in Taiwan is 13:41:04.
44
ctime() and localtime()
#include <iostream> #include <time.h> using std::cout; using std::endl; int main() { time_t t0; struct tm *newTime; time(&t0); cout << ctime(&t0); newTime = localtime( &t0 ); cout << newTime->tm_hour << ':' << newTime->tm_min << ':' << newTime->tm_sec << endl; return 0; } You may convert it to a well-formatted string, or break the time information to several fields. int tm_sec; // seconds (0 - 60) int tm_min; // minutes (0 - 59) int tm_hour; // hours (0 - 23) int tm_mday; // day of month (1 - 31) int tm_mon; // month of year (0 - 11) int tm_year; // year int tm_wday; // day of week (Sunday = 0) int tm_yday; // day of year ( )
45
Exercise on vector Create a vector
Iteratively add elements to the end by push_back(). Calculate the average time for adding a new element. Iteratively delete elements from the end by pop_back(). Calculate the average time for deleting an element. Iteratively add elements to the beginning by insert(). Calculate the average time for adding a new element. Iteratively erase elements from the beginning by erase(). Calculate the average time for deleting an element.
46
Exercise on deque Create a deque
Iteratively add elements to the end by push_back(). Calculate the average time for adding a new element. Iteratively delete elements from the end by pop_back(). Calculate the average time for deleting an element. Iteratively add elements to the beginning by push_front(). Calculate the average time for adding a new element. Iteratively erase elements from the beginning by pop_front(). Calculate the average time for deleting an element. You may measure by clock() or time(). Post your result to Moodle, by specifying how you measure the time.
47
List List<T> - the list container template See figures in P.652
You can insert or delete elements anywhere in the sequence in constant time. See figures in P.652
48
Create a List list<string> names;
Create an empty list List<string> sayings(20); A list of 20 empty strings list<double> values(50, ); A list of 50 values of type double; list<double> samples(++values.begin(), --values.end()); Copy the contents from the values list, except the first and the last elements You do not have random access iterators as with a vector or a deque container.
49
Adding Elements to a List
push_front() push_back() insert() list<int> data(5,1); // P.675 data.insert(++data.begin(), 77); data.insert(iter, 3, 88); data.insert(iter, numbers.begin(), numbers.end());
50
Accessing Elements in a List
front(), back() Using an iterator begin(), end() rbegin(), rend() You can only increment or decrement an iterator. Random access like begin()+2 is not allowed. Note that in Ex10_05.cpp, the code is iter != text.end() instead of iter < text.end() because lists only have bidirectional iterators, not random access iterators.
51
Ex10_05.cpp (P.677) Enter a few lines of text. Press Enter to end.
push_front() making the lines to be stored in reverse order. Replace it as push_back() to see the difference. Output the data using an iterator. Sort the data in ascending sequence. The list<T> templates defines its own sort() function member, because the sort() function defined in the algorithm header requires a random access iterator.
52
Other Operations on Lists
clear() Delete all the elements from a list erase(iter) Remove an element from a list erase(numbers.begin(), numbers.end()) Remove elements from a list merge() Merge two sorted lists
53
Other Operations on Lists (cont.)
remove() Remove elements from a list that match a particular value unique() Eliminate adjacent duplicate elements list data[] = {10, 22, 4, 10, 89, 22, 89, 10}; list<int> numbers(data, data+8); numbers.remove(22); numbers.sort(); numbers.unique();
54
Ex10_06.cpp (P.683) Defining a Predicate for Filtering a List
members.remove_if(is_negative<int>()); Note the two function templates listlist() and loadlist().
55
Exercise We are interested in 3 fields in a text file:
id nickname 24-39 source Define a class CEntry with three data members (id,nickname,source). Write a C++ program to read the file, and store the fields to a list of CEntry. Now enter an infinite loop to ask users to supply an id. Search the list to determine whether this id appears in the list. Bonus: also display the time which the computer took to search each id. End the program when the user inputs an empty string.
56
// This code fragment will extract the three fields from the file #include <iostream> #include <fstream> #include <string> using std::cout; using std::endl; using std::ifstream; using std::string; int main() { string line; ifstream user("T:\\ptt-user.txt"); while (getline(user, line, '\n') ) cout << line.substr(10,11) << '\t' << line.substr(23,16) << '\t' << line.substr(40,15) << endl; } return 0; Hint
57
Associate Containers (P.701)
map<K, T> You don’t need to search the whole list to retrieve a particular object. The location of an object of type T within an associative container is determined from a key of type K. The mechanism is also known as hash. The objects you store in a map are always a key/object pair The template type pair<K,T> is automatically included by the map header.
58
#include <iostream> #include <map> #include <string> using std::cout; using std::endl; using std::string; using std::map; int main() { map<string, int> score; score["Alice"] = 100; score["Bob"] = 70; score["Charlie"] = 60; cout << score["Bob"] << endl; cout << score.size() << endl; return 0; } A Simple Example
59
Defining Map Containers
Creating a map map<Person, string> phonebook; map<Person, string> phonebook(iter1, iter2); Storing Objects auto entry = pair<Person, string>(Person(“Mel”, “Gibson”), “ ”); auto entry = make_pair( Person(“Mel”, “Gibson”), “ ”); make_pair() automatically deduces the type for the pair, so it looks more elegant. You may use a typedef statement to abbreviate the pair<K,T> type (P.703) typedef pair<Person, string> Entry; Entry entry1 = Entry( Person(“Jack”, “Jones”), “ ”);
60
insert() Insert one or more pairs in a map phonebook.insert(entry1);
Note entry1 is an object with the pair type The function returns a value which is also a pair: The first object is an iterator The second is a value of type bool. true – the insertion was made. The iterator points to the element. false – the insertion failed (an element with the same key already exists in the map).
61
Check if an object was stored
map<Person, string> phonebook; auto checkpair = phonebook.insert(entry1); if (checkpair.second) cout << “Insertion succeeded.” << endl; else cout << “Insertion failed.” << endl;
62
Accessing Objects Use the subscript operator to retrieve the object from a map corresponding to a key string number = phonebook[Person(“Jack”, “Jones”)]; However, if the key is not in the map, the subscript operator will insert a pair entry for this key, with an object of default value. You could use the find() function to check whether there is an entry for a given key.
63
find() string number; Person key = Person(“Jack”, “Jones”); auto iter = phonebook.find(key); if (iter != phonebook.end()) { number = iter->second; cout << “The number is “ << number << endl; } else cout << “No number for the key “; key.showPerson();
64
Ex10_11.cpp (P.708) erase() ignore()
cout << setiosflags(ios::left) Remains in effect until the resetiosflags manipulator is used to restore right-justification.
65
Exercise: Map Repeat the previous exercise with BBS id.
Use a map (instead of a list) to store the data, and see whether the query speed becomes faster.
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.