Searching and Sorting Arrays Searching in ordered and unordered arrays Find the minimal element in an unordered array. Steps: 1. Initially, let the 0th element be the minimal element. 2. Then sweep through the array and see if we find something better. Find the minimal element in an unordered array. //Initially, let the 0th element be // the minimal element. int whereSmallest = 0; //Then sweep through the array // and see if we find something better. How? Find the minimal element in an unordered array. //Initially, let the 0th element be // the minimal element. int whereSmallest = 0; //Then sweep through the array // and see if we find something better. for (int i=1; i<A.length; i++) { //check for something better How? } Find the minimal element in an unordered array. //Initially, let the 0th element be // the minimal element. int whereSmallest = 0; //Then sweep through the array // and see if we find something better. for (int i=1; i<A.length; i++) { //check for something better if (A[i]<A[whereSmallest]) { whereSmallest = i; } } //at the end of the above loop, A[whereSmallest] is // the smallest element of A Find the maximal element in an unordered array. What needs to be changed? //Initially, let the 0th element be // the minimal element. int whereSmallest = 0; //Then sweep through the array // and see if we find something better. for (int i=1; i<A.length; i++) { //check for something better if (A[i]<A[whereSmallest]) { whereSmallest = i; } } //at the end of the above loop, A[whereSmallest] is // the smallest element of A Find the maximal element in an unordered array. What needs to be changed? //Initially, let the 0th element be // the minimal element. int whereLargest = 0; //Then sweep through the array // and see if we find something better. for (int i=1; i<A.length; i++) { //check for something better > if (A[i] A[whereLargest]) { whereLargest = i; } } //at the end of the above loop, A[whereLargest] is // the largest element of A What if the array is already sort? If the array is sorted in ascending order, where is the minimal element? We could search it as before but there is a better way. If the array is sorted in ascending order, where is the maximal element? What if the array is already sort? If the array is sorted in descending order, where is the minimal element? We could search it as before but there is a better way. If the array is sorted in descending order, where is the maximal element? Statistical median From wikipedia: “In probability theory and statistics, a median is a number dividing the higher half of a sample, a population, or a probability distribution from the lower half. The median of a finite list of numbers can be found by arranging all the observations from lowest value to highest value and picking the middle one. If there are an even number of observations, one often takes the mean of the two middle values.” Given a sorted array, we can write a function that determines the median. Statistical median public static double median ( int[] A ) { //determine if the array length is // odd of even double result = 0; … return result; } Statistical median public static double median ( int[] A ) { //determine if the array length is // odd of even double result = 0; if ((A.length%2)==0) { //is this the odd or even case? … } else { … } return result; } Statistical median public static double median ( int[] A ) { //determine if the array length is // odd of even double result = 0; if ((A.length%2)==0) { //even case so calc mean of middle 2 … } else { //odd case so pick middle one … This case is easier. } return result; } Statistical median public static double median ( int[] A ) { //determine if the array length is // odd of even double result = 0; if ((A.length%2)==0) { //even case so calc mean of middle 2 … } else { //odd case so pick middle one result = A[ A.length/2 ]; } return result; } Statistical median public static double median ( int[] A ) { //determine if the array length is // odd of even double result = 0; if ((A.length%2)==0) { //even case so calc mean of middle 2 result = ( A[ A.length/2-1 ] + A[ A.length/2 ] ) / 2.0; } else { //odd case so pick middle one result = A[ A.length/2 ]; } return result; } Recap So far we’ve: 1. 2. 3. Found min/max elements in unsorted and sorted arrays. Calculated median of sorted arrays. What if we would like to check whether or not an array contains a specified value? What type of thing should this function return? Searching an unordered (unsorted) array for a specific element. Unsorted search for specified element public static boolean unsortedSearch ( int[] A, int what ) { … } Unsorted search for specified element public static boolean unsortedSearch ( int[] A, int what ) { boolean found = false; //now search A for what … return found; } Unsorted search for specified element public static boolean unsortedSearch ( int[] A, int what ) { boolean found = false; //now search A for what for (int i=0; i<A.length; i++) { … } return found; } Unsorted search for specified element public static boolean unsortedSearch ( int[] A, int what ) { boolean found = false; //now search A for what for (int i=0; i<A.length; i++) { if (A[i]==what) { found = true; } } return found; } Unsorted search for specified element: another slightly more efficient way public static boolean unsortedSearch ( int[] A, int what ) { //search A for what for (int i=0; i<A.length; i++) { if (A[i]==what) { return true; } } return false; } An analysis of these two methods Let’s count the number of comparisons performed in: the best case the worst case the average case An analysis of these two methods Method A Method B public static boolean unsortedSearch ( int[] A, int what ) { boolean found = false; //now search A for what for (int i=0; i<A.length; i++) { if (A[i]==what) { found = true; } } return found; } public static boolean unsortedSearch ( int[] A, int what ) { //search A for what for (int i=0; i<A.length; i++) { if (A[i]==what) { return true; } } return false; } What are the number of comparisons for the best, worse, and average cases for each method? An analysis of these two methods Method A Method B public static boolean unsortedSearch ( int[] A, int what ) { boolean found = false; //now search A for what for (int i=0; i<A.length; i++) { if (A[i]==what) { found = true; } } return found; } public static boolean unsortedSearch ( int[] A, int what ) { //search A for what for (int i=0; i<A.length; i++) { if (A[i]==what) { return true; } } return false; } Best = N; worst = N; average = N. Best = 1; worst = N; average = N/2. Searching a sorted array for a specified element. We could treat the array as unsorted and search it but that would be inefficient. So let’s introduce the search method. binary Binary search first middle last Searching a sorted array for a specified element. public static boolean sortedSearch ( int[] A, int what, int first, int last ) { boolean foundIt = false; … return foundIt; } Searching a sorted array for a specified element. public static boolean sortedSearch ( int[] A, int what, int first, int last ) { boolean foundIt = false; //base case … return foundIt; } Searching a sorted array for a specified element. public static boolean sortedSearch ( int[] A, int what, int first, int last ) { boolean foundIt = false; //base case if (first>=last) { if (what==A[first]) foundIt = true; } else { … } return foundIt; } Searching a sorted array for a specified element. public static boolean sortedSearch ( int[] A, int what, int first, int last ) { boolean foundIt = false; //base case if (first>=last) { if (what==A[first]) foundIt = true; } else { int middle = (first+last) / 2; … } return foundIt; } Searching a sorted array for a specified element. public static boolean sortedSearch ( int[] A, int what, int first, int last ) { boolean foundIt = false; //base case if (first>=last) { if (what==A[first]) foundIt = true; } else { int middle = (first+last) / 2; if (what==A[middle]) … else if (what<A[middle]) … else … } return foundIt; } Searching a sorted array for a specified element. public static boolean sortedSearch ( int[] A, int what, int first, int last ) { boolean foundIt = false; //base case if (first>=last) { if (what==A[first]) foundIt = true; } else { int middle = (first+last) / 2; if (what==A[middle]) foundIt = true; else if (what<A[middle]) foundIt = sortedSearch( A, what, first, middle-1 ); else foundIt = sortedSearch( A, what, middle+1, last ); } return foundIt; An example of a } recursive function (a function that may call itself). Searching a sorted array for a specified element. private static boolean sortedSearch ( int[] A, int what, int first, int last ) { } boolean foundIt = false; An example of a “helper” //base case function (a function that helps if (first>=last) { get the recursion started; not if (what==A[first]) an “official” term). foundIt = true; } else { int middle = (first+last) / 2; Also an example of function if (what==A[middle]) overloading (an “official” term). foundIt = true; else if (what<A[middle]) foundIt = sortedSearch( A, what, first, middle-1 ); else foundIt = sortedSearch( A, what, middle+1, last ); } return foundIt; public static boolean sortedSearch ( int[] A, int what ) { return sortedSearch( A, what, 0, A.length-1 ); } Searching a sorted array for a specified element. private static boolean sortedSearch ( int[] A, int what, int first, int last ) { //base case Arguably simpler with returns. if (first>=last) { if (what==A[first]) return true; } else { int middle = (first+last) / 2; if (what==A[middle]) return true; else if (what<A[middle]) return sortedSearch( A, what, first, middle-1 ); else return sortedSearch( A, what, middle+1, last ); } return false; } public static boolean sortedSearch ( int[] A, int what ) { return sortedSearch( A, what, 0, A.length-1 ); } Searching a sorted array for a specified element. public static boolean sortedSearch ( int[] A, int what ) { if (A.length==0) return false; //empty! } int first = 0, last = A.length - 1; while (first<last) { int middle = (first+last) / 2; if (what == A[middle]) return true; if (what < A[middle]) last = middle - 1; else first = middle + 1; } if (what==A[first]) return true; return false; Non recursive version. Summary Searching in an unordered array (of length N) requires us to search N elements in the worst case. Searching in an ordered array (also of length N) requires us to search log2 elements in the worst case. Summary Searching in an unordered array (of length N) requires us to search N elements in the worst case. So searching 1,000,000,000 things requires searching 1,000,000,000 things. Searching in an ordered array (also of length N) requires us to search log2 elements in the worst case. So searching 1,000,000,000 things requires searching only 30 things! At most! Sorting an array: the selection sort Sorting An arrangement or permutation of data May be either: ascending (non decreasing) descending (non increasing) Selection sort Based on the idea of repeatedly finding the minimal elements. But first, how can we find the (single, most) minimal element in an array? Selection sort How can we find the (single, most) minimal element in an array? … //let 0 be the location of the smallest element so far int whereSmallest = 0; for (int i=1; i<A.length; i++) { if (A[i]<A[whereSmallest]) { whereSmallest = i; } } System.out.println( "the smallest is " + A[whereSmallest] + " which was located at position " + whereSmallest + "." ); … Selection sort Idea: Find the smallest in A[0]..A[ A.length-1 ]. Put that in A[0]. Then find the smallest in A[1]..A[ A.length-1 ]. Put that in A[1]. … But first, let’s develop a swapPairs function that swaps a pair of elements denoted by a and b in some array, A. <-1, 2, 4, -5, 12> <-5, 2, 4, -1, 12> Selection sort public static void swapPair ( … ) { … } What do we need in here to do the job (function parameters)? Selection sort public static void swapPair ( int[] A, int a, int b ) { … } What do we need in here to do the job (function parameters)? Selection sort public static void swapPair ( int[] A, int a, int b ) { int temp = A[a]; A[a] = A[b]; A[b] = temp; } Selection sort public static void swapPair ( int[] A, int a, int b ) { int temp = A[a]; A[a] = A[b]; A[b] = temp; } Why doesn’t this work? public static void swapPair ( int a, int b ) { int temp = a; a = b; b = temp; } Selection sort Idea: Find the smallest in A[0]..A[ A.length-1 ]. Put that in A[0]. Then find the smallest in A[1]..A[ A.length-1 ]. Put that in A[1]. … //let 0 be the location of the smallest element so far int whereSmallest = 0; for (int i=1; i<A.length; i++) { if (A[i]<A[whereSmallest]) { whereSmallest = i; } } swapPairs( A, 0, whereSmallest ); Selection sort Idea: Find the smallest in A[0]..A[ A.length-1 ]. Put that in A[0]. Then find the smallest in A[1]..A[ A.length-1 ]. Put that in A[1]. … for (int j=0; j<A.length; j++) { //let j be the location of the smallest element so far int whereSmallest = j; for (int i=j+1; i<A.length; i++) { if (A[i]<A[whereSmallest]) { whereSmallest = i; } } swap( A, j, whereSmallest ); }