350 likes | 365 Views
The grades for Midterm 2 and Homework 5 have been announced. Homework 6 is finished and Homework 7 has been assigned, due on May 24th. The final exam is on May 29th at 16:00. This announcement also includes information on searching a vector, sequential search, counting search, one occurrence search, binary search, and selection sort.
E N D
Announcements • Midterm2 grades were announced • Homework5grades were announced • Homework 6 finished • Homework 7is assigned this week, will be DUE next week May 24th Wednesday • FINAL exam is on May 29thMonday at 16:00.
Searching a vector • We can search for one occurrence, return true/false or the index of occurrence • Search the vector starting from the beginning • Stop searching when match is found • We can search and count the number of occurrences and return count • Search entire vector • Similar to one occurrence search, but do not stop after first occurrence • We can search for many occurrences, but return occurrences in another vector rather than count • In all these cases, we search the vector sequentially starting from the beginning • This type of search is called “sequential search”
Counting search int countmatches(const vector<string> & a, const string& s) // post: returns # occurrences of s in a { int count = 0; int k; for(k=0; k < a.size(); k++) { if (a[k] == s) { count++; } } return count; } • How can we change this code to return the index of the first occurrence? • see next slide
One occurrence search int firstmatch(const vector<string> & a, const string& s) // post: returns the index of occurrence of s in a, -1 // otherwise { int k; for(k=0; k < a.size(); k++) { if (a[k] == s) { return k; } } return -1; } • Does not search the entire array if one match is found • good for efficiency purposes • How could you modify this to return true/false?
Collecting search • Collect the occurrences in another vector void collect(const vector<string> & a, vector<string> & matches) // pre: matches is empty // post: matches contains all elements of a with // first letter 'A' { int k; for (k=0; k < a.size(); k++) { if (a[k].substr(0,1) == "A") { matches.push_back(a[k]); } } }
Binary search • Alternative to sequential search for sorted vectors • If a vector is sorted we can use the sorted property to eliminate half of the vector elements with one comparison • What number (between 1 and 100) do we guess first in number guessing game? • Idea of creating program to do binary search • Check the middle element • If it has the searched value, then you’re done! • If not, eliminate half of the elements of the vector • search the rest using the same idea • continue until match is found or there is no match • how could you understand that there is no match? • let’s develop the algorithm on an example • we need two index values, low and high, for the search space
Binary Search (search for 62) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 102434 5255 62 67 75 80 819092100101111 low=0 mid=7high=14 low=0mid=3high=6 low=4 high=6 mid=5 => FOUND
Binary Search (search for 60) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 102434 5255 62 67 75 80 819092100101111 low = 0 mid=7high =14 low=0 mid=3high=6 low=4 high=6 mid=5 low=4 high=4 mid=4 low=5 high=4 => NO MATCH FOUND – STOP
Binary search code int bsearch(const vector<string>& list, const string& key) // pre: list.size() == # elements in list // post: returns index of key in list, -1 if key not found { int low = 0; // leftmost possible entry int high = list.size()-1; // rightmost possible entry int mid; // middle of current range while (low <= high) { mid = (low + high)/2; if (list[mid] == key) // found key, exit search { return mid; } else if (list[mid] < key) // key in upper half { low = mid + 1; } else // key in lower half { high = mid - 1; } } return -1; // not in list }
Comparing Sequential and Binary Search • Given a list of N elements: • Binary search makes on the order of log N operation O(log N) • Linear (sequential) search takes on the order of N operations O(N)
Sorting • One of the fundamental operations in Computer Science • Given a randomly ordered array, sort it • ascending • descending • Many algorithms exists • some in Chapter 11 • we will discuss two of them – Selection Sort (11.1.1) and Insertion Sort (11.1.2) • Analysis in 11.4
Selection Sort • N is the number of elements in vector/array • Find smallest element, move into 0thvector/array location • examine all N elements • 0 .. N-1 • Find next smallest element, move into 1st location • 0th location is already the minimum • examine N-1 elements • 1 .. N-1 • Find next smallest element, move into 2nd location • 0th and 1st locations are already the minimum two elements • examine N-2 elements • 2 .. N-1 • Generalize for kth element, 0 <= k <= N-2 - find the minimum between kth and last element (element with index N-1) of array - swap the kth element with the minimum one
Selection Sort: The Code void SelectSort(vector<int> & a) // pre: a contains a.size() elements // post: elements of a are sorted in non-decreasing order { int j, k, temp, minIndex, numElts = a.size(); for(k=0; k < numElts - 1; k++) { minIndex = k; // minimal element index for(j=k+1; j < numElts; j++) { if (a[j] < a[minIndex]) { minIndex = j; // new min, store index } } temp = a[k]; // swap min and k-th elements a[k] = a[minIndex]; a[minIndex] = temp; } }
insertion and deletion • It’s easy to insert at the end of a vector, use push_back() • However, if the vector is sorted and if we want to keep it sorted, then we can’t just add to the end • We have to find an appropriate position to insert the element and do some shifts. • If we need to delete an element from a sorted vector, how can we “close-up” the hole created by the deletion? • Shift elements left by one index, decrease size • We decrease size using pop_back() pop_back() changes size, not capacity
Inserting an element into a sorted array 2 7 11 18 21 22 26 89 99 • InsertNewNum which is e.g.23 • Is the array “capacity” sufficient for an extra element? • What would you do to insert newNum in the right spot?
Insertion into sorted array 012 34 5 6 7 8 2 7 11 18 21 22 26 89 99 NewNum = 23 2 7 11 18 21 22 2626 89 99 012 34 5 6 7 8 9
Insert into sorted vector void insert(vector<int>& a, int newnum) // NOT const vector // pre: a[0] <= … <= a[a.size()-1], a is sorted // post: newnum inserted into a, a still sorted { int count = a.size(); //size before insertion a.push_back(newnum); //increase size – newnum is inserted at // the end but the inserted value is not important int loc = count; // start searching insertion loc from end while (loc>0 && a[loc-1] > newnum) { a[loc] = a[loc-1]; loc--; // shift right until the proper insertion cell } a[loc] = newnum; //actual insertion } • See vectorproc.cpp (not in book)
What about deletion? • Remove the element at a given position (pos) void remove(vector<string>& a, int pos) // post: original a[pos] removed, size decreased { int lastIndex = a.size()-1; a[pos] = a[lastIndex]; a.pop_back(); } • What about if vector is sorted, what changes? • What’s the purpose of the pop_back() call?
Deletion from sorted vector Ex: Delete element at position 3 012 34 5 6 7 8 Size is 9 2 7 11 18 21 22 26 89 99 First shift all elements on the right of 3rd element one cell to the left 012 34 5 6 7 8 2 7 11 2122 26 89 9999 pop back the last element of vector 012 34 5 6 7 2 7 11 21 22 26 89 9999 Size is now 8
Deletion from sorted vector void remove(vector<int> & a, int pos) // pre: a is sorted // post: original a[pos] removed, a is still sorted { int lastIndex = a.size()-1; int k; for(k=pos; k < lastIndex; k++) { a[k] = a[k+1]; } //shift all elements on the right of pos one cell left a.pop_back(); //remove the last element of the array } • Does pop_back() actually remove an element? • no, it just decreases the size so that the last element becomes unreachable • Capacity remains the same • See vectorproc.cpp (not in book)
Insertion Sort • Insert 1st element before or after 0th • first 2 sorted • Insert 2nd element (element with index 2) in proper location • first 3 sorted • Generalize • insert kth element (element with index k) within first k elements • first k+1 sorted • run this for all k between 1 .. N-1
Insertion Sort – The Code void InsertSort(vector<string> & a) // precondition: a contains a.size() elements // postcondition: elements of a are sorted in non-decreasing order { int k,loc, numElts = a.size(); for(k=1; k < numElts; k++) { string hold = a[k]; // insert this element loc = k; // location for insertion // shift elements to make room for hold (i.e. a[k]) while (0 < loc && hold < a[loc-1]) { a[loc] = a[loc-1]; loc--; } a[loc] = hold; } }
Which one faster? • No exact answer! It depends on the vector to be sorted • already ordered, totally disordered, random • Let’s see how many iterations do we have in Selection Sort • Outer loop k: 0 .. N-2 • Inner loop j: k+1 .. N-1 • (N-1) + (N-2) + (N-3) + .. + 1 = N(N-1)/2 = (N2 – N)/2 • Worst case, best case, average case??? • Complexity is O(N2) • order of N2 • Big-oh notation used to describe algorithmic complexities. This is not a precise amount of operations and comparisons. Minor terms and coefficients are not taken into consideration
Which one faster? • Let’s analyze Insertion Sort • Outer loop k: 1 .. N-1 • N-1 iterations for the outer loop • What about inner loop? • worst case, best case differ • worst case: k times, so total is 1+2+3+…+(N-1) = N(N-1)/2, complexity is O(N2) • best case: inner loop does not iterate, complexity is O(N), but best case complexity analysis is not done too often • what are the best and worst cases? • average case: inner loop iterates k/2 times, order is still O(N2) • Complexities of both Selection and Insertion Sort are O(N2) • Which one would you prefer to use? • Let’s run timesorts.cpp (modified from book) – needs several Tapestry .h and .cpp files in the project folder to run (comparer.h, ctimer.h, ctimer.cpp, prompt.h, prompt.cpp, randgen.h, randgen.cpp, sortall.h, sortall.cpp – red ones to be added to the project).
Built-in Arrays • C++ native array type • Two versions • fixed size arrays • array size is fixed and must be specified with a constant expression at the declaration • we will see this type now • array pointers • array size is dynamically allocated • we will not see it in this course • use of both types are the same except definition • vector versus built-in arrays • vector is a class based on built-in arrays • vector has member functions and operators, built-in arrays do NOT • vector is more flexible, but slower
Built-in Array declaration • As we said, we will discuss fixed size built-in arrays, not the pointer version with dynamic allocation • size must be able to be determined at compile time • constant, literal or an expression that involves constants and literals only const int CLASSSIZE = 100; // constant string names[CLASSIZE]; // array of 100 strings double grades[CLASSIZE*5]; // array of 500 doubles int list[200]; // array of 200 integers • The following array declaration is INVALID int size; cout "Enter how many students ? "; cin >> size; string names[size]; // array size cannot be a variable
Built-in array initialization at declaration • You may specify a list of initial values at declaration. See following example: string dayNames [] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday","Friday", "Saturday"}; • dayNames is an array with 7 elements of type string • 0th element is “Sunday”, 1st is “Monday”, ... • not necessary to specify size (7), since the number of elements make the size clear • but you can specify the size, if you wish string dayNames [7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday","Friday", "Saturday"};
Assignment rules in arrays • vectors withthesame element typecan be assigned to each other by = • LHS vector becomes the same as the RHS vector • size and capacity also become the same • Built-in arrays cannot be assigned to each other by = int coins[] ={1,5,10,25}; int temp[4]; temp = coins; // illegal temp[1] = coins[2]; // legal – array element assignment • How can we assign coins to temp? • element by element for (i=0; i<4; i++) temp[i] = coins[i];
Passing built-in arrays as parameters • A built-in array can be passed only as reference parameter or const-reference parameter • cannot be passed as value parameter • But, we do not use ampersand character, &, at parameter declaration • and we do not specify the array size in array parameter • however array size is generally passed as another integer parameter since we do not have a size() member function for built-in arrays void Change(int list[], intnumElts); void Print(const int list[], intnumElts); reference parameter const-reference parameter
Built-in array demo • See fixlist.cpp (slightly modified from the version in book) • Why did we use const in Print? • to avoid accidental changes in array list • Why did we pass numEltsas parameter for the number of elements in the array? • because we don’t know the total number of elements in the array while writing the functions
Example – Fibonacci numbers • Used in many areas of Mathematics and Computer Science F0 = 1 F1 = 1 Fn = Fn-1 + Fn-2 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 • You can see many examples of Fibonacci numbers in nature • E.g. Increase of number of branches of trees in time • See http://www.mcs.surrey.ac.uk/Personal/R.Knott/Fibonacci/fibnat.html for more examples const int MAX_SIZE = 100; int list[MAX_SIZE]; int k; list[0] = list[1] = 1; for (k=2; k < MAX_SIZE, k++) { list[k] = list[k-1]+list[k-2]; }
Use of strings as arrays • Characters in a string can be referred as an array using [ ] string s="cs201"; ... s[0] = 'n'; // makes 0th character of s 'n' ... for (k=0; k<s.length(); k++) cout << s[k] << ""; • In general, s[k]means s.at(k)
The Matrix • To represent two dimensional arrays • Given rows and columns: • We define a matrix as a vector of vectors vector<vector<int>> mat(rows, vector<int>(cols)); vector<vector<int>> mat(3, vector<int>(5)); mymatrix[2][3] = 100; • First index is for row, second is for column 0 1 2 3 4 0 1 2
Possible Matrix definitions • Possible matrix declarations • 4 different declarations vector<vector<int>> matrix_name; empty matrix (zero rows, zero columns) vector<vector<int>> matrix_name(rows); matrix with rows many empty vector<int>’s vector<vector<int>> matrix_name(rows, vector<int>(cols)); matrix with rows*colselements all initialized to 0 vector<vector<int>> matrix_name(rows, vector<int>(cols, init_value)); matrix with rows*colselements all initialized to init_value
To get the size of rows and columns mymatrix.size() • number of rows in matrix mymatrix[0].size() • number of columns in matrix • Example: Let’s run matdemo.cpp