Week 11 Introduction to Computer Science and Object-Oriented Programming COMP 111 George Basham Week 11 Topics 11.1.1 Sorting: selection, insertion and bubble sort 11.1.2 Profiling the Selection Sort Algorithm 11.1.3 Analyzing the Performance of the Selection Sort Algorithm 11.1.4 Searching 11.2.1 Binary Search 11.1.1 Sorting • A sorting algorithm rearranges the elements of a collection so that they are stored in sorted order • A collection can be sorted in ascending order (from low to high) or in descending order (from high to low) • There are many algorithms for sorting, the most common introductory ones are the selection, insertion and bubble sorts 11.1.1 Sorting Cont. (selection) • The selection sort works by selecting the smallest unsorted item remaining in the list, and then swapping it with the item in the next position to be filled, working from “left to right” • A selection sort is a simple algorithm and is easy to implement • A selection sort is inefficient for large lists 11.1.1 Sorting Cont. (selection) • The selection sort is a comparison sort that works as follows: – Find the minimum value in the list – Swap it with the value in the first position – Sort the remainder of the list (excluding the first value) • The next value to “the right” becomes the new beginning of the unsorted section of the list and the algorithm above is repeated for the unsorted section until every element in the list (except the last element) is compared (source: Wikipedia) 11.1.1 Sorting Cont. (selection) Initial state Begin first pass 11 9 17 5 12 11 9 17 5 12 5 9 17 11 12 Min value for pass 1 is: 5 Begin second pass Min value for pass 2 is: 9 11.1.1 Sorting Cont. (selection) Begin third pass 5 9 17 11 12 5 9 11 17 12 5 9 11 12 17 Min value for pass 3 is: 11 Begin fourth pass Min value for pass 4 is: 12 Final state Collection is now selection sorted in ascending order. 11.1.1 Sorting Cont. (selection) // SELECTION SORT public static int [ ] selSort(int arr[ ], int left, int right) { // left is beginning of unsorted section for (int i = left; i < right; ++i) { int min = i; for (int j = i; j < right; ++j) // find the min element if (arr[min] > arr[j]) min = j; // swap the minimum element int temp = arr[min]; arr[min] = arr[i]; arr[i] = temp; { return arr; } 11.1.1 Sorting Cont. (insertion) • An insertion sort works by choosing the next unsorted element and finding where to insert it in the sorted section. When the location is found it then shifts elements to the right and drops the element into place. • An insertion sort is a simple algorithm and is easy to implement • An insertion sort is inefficient for large lists, but is somewhat more efficient than a selection or a bubble sort 11.1.1 Sorting Cont. (insertion) • The insertion sort is a comparison sort that works as follows: – Start with the second element in the list as the target – Compare the target to the first element, if target is smaller in value, slide the first element to the “right” and put the value of the target into the first element • The third element then becomes the target, and again you “work backwards”, comparing target to element two then one if necessary. At the point target is greater than element to the left, push previous larger elements to the right and put target value in that position. Continue in like with next element to the right until all elements are “targeted”. 11.1.1 Sorting Cont. (insertion) Initial state Begin first pass 11 9 17 5 12 11 9 17 5 12 9 11 17 5 12 1st pass begins at pos 2 Begin second pass 2nd pass begins at pos 3 11.1.1 Sorting Cont. (insertion) Begin third pass 9 11 17 5 12 5 9 11 17 12 5 9 11 12 17 3rd pass begins at pos 4 Begin fourth pass 4th pass begins at pos 5 Final state Collection is now insertion sorted in ascending order. 11.1.1 Sorting Cont. (insertion) // INSERTION SORT public static int [ ] insSort(int arr[ ], int left, int right) { for (int i = left+1; j < right; ++i) { int j, val = arr[i]; // locate position to place target element for ( j= i-1; j >= left && arr[j] > val; --j) arr[j+1] = arr[j]; // slide each element to the right arr[j+1] = val; // drop element into position } return arr; } 11.1.1 Sorting Cont. (bubble) • The bubble sort (also called the exchange sort) works by repeatedly stepping through the list to be sorted, comparing two items at a time, swapping these two items if they are in the wrong order. The pass through the list is repeated until no swaps are needed, which means the list is sorted. The algorithm gets its name from the way smaller elements "bubble" to the top (i.e. head) of the list via the swaps. • The bubble sort is a simple algorithm and is easy to implement, but is inefficient for large lists 11.1.1 Sorting Cont. (bubble) • The bubble sort is a comparison sort that works as follows (source - Wikipedia): – Compare adjacent elements. If the first is greater than the second, swap them. – Do this for each pair of adjacent elements, starting with the first two and ending with the last two. At this point the last element should be the greatest. – Repeat the steps for all elements except the last one. – Keep repeating for one fewer element each time, until you have no more pairs to compare. 11.1.1 Sorting Cont. (bubble) Initial state 11 9 17 5 12 Begin first pass 11 9 17 5 12 9 11 5 12 17 1st pass compare pattern: Begin second pass 2nd pass compare pattern: 11.1.1 Sorting Cont. (bubble) Begin third pass 9 5 11 12 17 5 9 11 12 17 5 9 11 12 17 3rd pass compare pattern: Begin forth pass 4th pass compare pattern: Final state Collection is now bubble sorted in ascending order. 11.1.1 Sorting Cont. (bubble) // BUBBLE SORT public static void bubbleSort(int data[ ]) { boolean isSorted; int tempVar; int passes = 0; do { isSorted = true; for (int i = 1; i < data.length - passes; i++) { if (data[i] < data[i - 1]) { // swap logic tempVar = data[i]; data[i] = data[i - 1]; data[i - 1] = tempVar; isSorted = false; } } passes++; } while (!isSorted); // continue if a swap took place } 11.1.2 Profiling the Selection Sort Algorithm • An important aspect of studying algorithms is to determine the complexity of a given algorithm • Complexity in computer science is usually measured two ways: space complexity and time complexity • Space complexity is a measure of the amount of memory an algorithm takes in its execution, while time complexity is a measure of the amount of time an algorithm takes in its execution 11.1.2 Profiling the Selection Sort Algorithm Cont. • Often an inverse relationship exists: time can be reduced if space is increased, and vice-versa • Determining the complexity of an algorithm can be done two ways: mathematical analysis (covered in the next section) and profiling • Profiling is the process of gathering runtime statistics about programs, such as execution time, memory usage, and method call counts 11.1.2 Profiling the Selection Sort Algorithm Cont. Sort time in milliseconds for various array sizes Elements Bubble Selection Insertion 2,560 31 15 15 5,120 125 47 31 20,480 1,969 875 563 81,920 31,391 14,047 9,125 The interesting characteristic of this data is that for each of the sorting algorithms, as the number of elements doubles, the sorting time roughly quadruples 11.1.3 Analyzing the Performance of the Selection Sort Algorithm • To do a selection sort requires finding the smallest value (up to n visits) and then swapping the elements (two visits). • The algorithm can be expressed as the equation: 1/2 n² + 5/2 n - 3 • The above can be reduced to the fastest growing term n² • Thus the selection sort using big-Oh notation is called an O(n²) algorithm. Doubling the data set means a fourfold increase in processing time. 11.1.4 Searching • To find a value in an unordered collection you must use a linear search (also called a sequential search) • A linear search examines all values in a list until it finds a match or reaches the end • A linear search locates a value in a list in O(n) steps • A linear search is a very inefficient way to find a value in a large list 11.2.1 Binary Search • A binary search is a technique for finding a particular value in a sorted linear array, by ruling out half of the data at each step • A binary search finds the median, makes a comparison to determine whether the desired value comes before or after it, and then searches the remaining half in the same manner • A binary search is an example of a divide and conquer algorithm (source – Wikipedia) 11.2.1 Binary Search Cont. An example of binary search in action is a simple guessing game in which a player has to guess a positive integer selected by another player between 1 and N, using only questions answered with yes or no. Supposing N is 16 and the number 11 is selected, the game might proceed as follows. • Is the number greater than 8? (Yes) • Is the number greater than 12? (No) • Is the number greater than 10? (Yes) • Is the number greater than 11? (No) Therefore, the number must be 11. At each step, we choose a number right in the middle of the range of possible values for the number. For example, once we know the number is greater than 8, but less than or equal to 12, we know to choose a number in the middle of the range [9, 12] (either 10 or 11 will do). Source - Wikipedia 11.2.1 Binary Search Cont. // BINARY SEARCH public static int bSearch(int[ ] array, int value, int left, int right) { // Continue while left and right haven't // become equal or crossed over each other while (left < right) { // locate middle index between left and right int mid = (left + right) / 2; if (array[mid] < value) left = mid + 1; // in right half else if (array[mid] > value) right = mid; // in left half else return mid; // found it } return -1; // not found } Reference: Big Java 3rd Edition by Cay Horstmann 11.1.1 Sorting: selection, insertion and bubble sort (section 1941 in Big Java) 11.1.2 Profiling the Selection Sort Algorithm (section 14.2 in Big Java) 11.1.3 Analyzing the Performance of the Selection Sort Algorithm (section 14.3 in Big Java) 11.1.4 Searching (section 14.6 in Big Java) 11.2.1 Binary Search (section 14.7 in Big Java)