250 likes | 400 Views
Lecture 21. What will I learn in this lecture?. Understand various methods of sorting. Use the qsort function to sort. Binary search Related Chapter: ABC 8.5. Sorting.
E N D
What will I learn in this lecture? • Understand various methods of sorting. • Use the qsort function to sort. • Binary search • Related Chapter: ABC 8.5
Sorting To sort means to put in place or rank according to kind, class or nature. For example, consider a herd of cows. We can sort the cows by weight, age, amount of milk produced, etc. . The sort can be in ascending or descending order. Note that we could not include a lizard in among the sort if we were sorting with respect to amount of milk produced. That is, the items we want to sort must have the same nature. In C we will use arrays to do our sorting. Since the data-type(kind, class or nature) for each element of the array must be the same we are able to compare any two elements in the array (no lizards in the array of milk producing cows). Why sort? One application of sorting is the need to have a sorted array to use binary search.
One method of sorting is called “selection sort”.The algorithm: find the smallest element in the list and swap the first item in the list with the smallest value.For example, suppose you are given the values(below): 5 3 7 2 4 ( 2 is the smallest value ) step 1 2 3 7 5 4 ( swap 2 with 5, now 3 is the smallest element) step 2 2 3 7 5 4 ( 3 is in place don’t swap, now 4 is the smallest element) step 3 2 3 4 5 7 ( swap 4 with 7, now 5 is the smallest element) step 4 2 3 4 57 ( 5 is in place don’t swap, 7 is in place )
Another method of sorting is called “insertion sort”. You use insertion sort when you sort a hand of cards. For example, suppose you are given the five cards (below): 5 3 7 2 4 (cards in Right hand) empty (cards in Left hand) step 1 3 7 2 4 (Right hand) 5 (Left hand) step 2 7 2 4 ( R ) 3 5 ( L ) step 3 2 4 ( R ) 3 5 7 ( L ) step 4 4 ( R ) 2 3 5 7 ( L ) step 5 empty ( R ) 2 3 4 5 7 ( L ) ( the cards are now sorted )
Sorting Insertion sort is faster than selection sort because it is easy to determine where we should add the next card to the left hand since the cards in the left hand are already sorted. In C we could use a version of binary search(Lecture 21-22) to tell us where to put the next card (in the left hand). Binary search is used only on the cards in the left hand since binary search only works on sorted arrays. Again, binary search is fast since it uses the transitive property of a sorted list of numbers. We will not have to write the C code for insertion sort, the built-in C function “qsort” (ABC p. 372 - implements a sorting algorithm that also uses the transitive property. See the example using qsort starting on the next slide.
qsort - Sorting an array 1. Problem Definition Write a program that sorts the values in an array in ascending order. Use the built-in function ‘qsort’ to do the work of sorting. 2. Refine, Generalize, Decompose the problem definition (i.e., identify sub-problems, I/O, etc.) Input = Array of integers. Output= Sorted array of integers (ascending order) is printed.
#include <stdio.h> #include <stdlib.h> int compare(int *ptr1, int *ptr2) { if ( *ptr1 > *ptr2) return 1; else if ( *ptr1 < *ptr2) return -1; else return 0; } void main(void) { int numbers[100]; int k,i=0; printf("Enter an array of no more than 100 integers.\n"); while (EOF != scanf("%i",&numbers[i])) ++i; qsort(numbers, i, sizeof(numbers[0]), compare); for (k=0; k<i; k++) printf("%i ", numbers[k]); printf("\n"); }
qsort - Sorting an array Execution: unixprompt>./a.out Enter an array of no more than 100 integers. 3 4 2 1 5 (hit Enter and then Control-d to signal EOF) 1 2 3 4 5 (this is the output the program produces) unixprompt>
Sorting Example - qsort The qsort function is a built-in C function that sorts values in an array. The algorithm behind qsort is called “Quick Sort” . In CS101 we are interested only in how to call this function. (see ABC p. 372-) The general format of the qsort function is: qsort(arrayname,elts,size_of_elts,compare_function) arrayname - is the name of an existing array. This array can have any data-type. It can even be an array of pointers. We will refer to the array’s type as datatype . elts is the number of elements of array.
Sorting Example - qsort qsort(arrayname,elts,size_of_elts,compare_function) size_of_elts is the size in bytes of each element in the array. Use the built-in operator sizeof that returns an integer value representing the number of bytes a variable or data-type takes up in RAM. Example: sizeof(integer) returns the value 4 on the Lab machines. sizeof(numbers[0]) returns the number of bytes the variable numbers[0] takes up in RAM, which is 4 since numbers is an integer array. compare_function is the name of the user defined function that actually does the comparison.
Sorting Example - compare_function The general format of the header for the user defined compare function is: int compare_function( datatype * ptr1,datatype * ptr2) qsort will call the compare_function and pass two pointers ptr1 and ptr2 . Both ptr1 and ptr2 “point” to values in the array arrayname (see previous slide). The user must code the function compare_function so that it returns an integer value back to qsort (the function that called compare_function) . qsort will use this integer to determine whether or not to swap the values in the array. To sort in ascending order the return value is: 0 if the elements *ptr1 and *ptr2 of the array are equal positive if *ptr1 > *ptr2 (i.e. swap the array values)negative if *ptr1 < *ptr2 (i.e. don’t swap the array values)
Sorting Example - compare_function Writing the code for compare_function depends on the data-type datatype and whether the data is sorted in ascending order, descending order, ... or by some other rule. Therefore it’s not possible to write one version of compare_function that does all.
Sorting Example The datatype in the sorting example is int . Therefore the header for the compare_function has the form: int compare( int * ptr1,int * ptr2) where ptr1 and ptr2 are pointers to values in the array numbers . As an example of how qsort works with compare see the pictures of memory in the following slides.
Sorting Example . . . ptr1 ptr2 numbers[0] numbers[1] numbers[4] 2000 2004 3 4 2 1 5 Address 2000 2004 … Suppose qsort called the compare function and *ptr1 is “3” and *ptr2 is “4”. The picture above shows this situation. In this example, we want to tell qsort to sort 3 before 4(don’t swap the values). To do this, we use *ptr1 and *ptr2 . Since *ptr1 < *ptr2 ( 3 < 4) we return a -1 value to qsort. That’s why we have the code(slide 20): else if ( *ptr1 < *ptr2) { return -1;
Sorting Example ptr1 ptr2 numbers[1] numbers[2] numbers[4] . . . 2004 2008 3 4 2 1 5 Address 2000 2004 2008… Now suppose qsort called the compare function and *ptr1 is “4” and *ptr2 is “2”. The picture above shows this situation. In this example, we want to tell qsort to sort 2 before 4( swap the values). To do this, we use *ptr1 and *ptr2 . Since *ptr1 > *ptr2 ( 4 > 2) we return +1 value to qsort. That’s why we have the code(slide 20): if ( *ptr1 > *ptr2) { return 1; }
Compiler Warning Messages The previous code works correctly but will generate a warning message. We can avoid the error messages if we obey the rules that qsort expects the compare_function to observe. The code on the next slide will sort the numbers as before but gcc will not display any warning messages. In the compare function (on the next slide), note the use of the void pointer data-type and the use of the cast operators on the pointer variables. The const (ABC p. 17)modifier in a variable declaration means that it is constant. e.g.const int x = 1; x = 2; /* illegal */
#include <stdio.h> #include <stdlib.h> int compare(const void *ptr1, const void *ptr2) { if ( *(int *)ptr1 > *(int *)ptr2) return 1; else if ( *(int *)ptr1 < *(int *)ptr2) return -1; else return 0; } void main(void) { int numbers[100]; int k,i=0; printf("Enter an array of no more than 100 integers.\n"); while (EOF != scanf("%i",&numbers[i])) ++i; qsort(numbers, i, sizeof(numbers[0]), compare); for (k=0; k<i; k++) printf("%i ", numbers[k]); printf("\n"); }
Compiler Warning Messages In ABC p. 372 you will find a detailed discussion of the function definition line of qsort and why the compare_function should have the format described on the previous slide in order to avoid gcc writing warning messages. The key idea is that you want qsort to work with an array of any data-type. Therefore the function definition line of qsort cannot fix the data-type of the compare_function arguments. A void pointer, void *ptr; is a pointer that points to data-type void (nothing). The program on the next slide shows that we can use a single pointer of data-type, pointer to void, to point to values of different data-types.
#include <stdio.h> void main(void){ int z = 3; float w = 4.0; void * ptr; ptr = &z; /* add one to z */ *(int *)ptr = *(int *)ptr + 1; /* cast ptr */ ptr = &w; /* add 1.0 to w */ *(float *)ptr = *(float *)ptr + 1.0; /* cast ptr */ printf("z = %i \n",z); /* prints 4 */ printf("w = %f \n",w); /* prints 5.000 */ }
Compiler Warning Messages Compiling the code on the previous slide does not generate a warning message when the variable ptr is used. However, if we defined the pointer variable ptr (in the program on the previous slide) as int * ptr; then gcc would generate a compiler warning message when compiling the statement, ptr = &w;
Example - Binary Search 1. Problem Definition Write a function named “binSearch” that searches a list of integers to find a match given a user supplied value. It is assumed that the list is sorted in ascending order. If a match is found then the function returns the index of the array otherwise the function returns -1. The main idea is: if the value is greater than the middle value, then search the right half of the list, else if the value is less than the middle value, search the left half of the list, else the value equals the middle value, return the index of the middle value.
Example - Binary Search 2. Refine, Generalize, Decompose the problem definition (i.e., identify sub-problems, I/O, etc.) Input = an integer from the user. For test purposes we will say the list has the values {5, 8, 9, 10, 14} Output= an integer in the range {-1, 0, 1, 2, 3, 4}
#include <stdio.h> int binSearch(int array[], int size, int value); /*prototype*/ void main(void) { int index; int value; int list[] = {5,8,9,10,14}; printf("Enter a search value:"); scanf("%i",&value);/* the function binSearch returns the index of the array */ /* where the match is found, otherwise a –1 */ index = binSearch(list,5,value); if (index == -1) printf("Value not found!\n"); else printf("Value matches the %i element in the array!\n",++index); } /* code continued on next slide */
/* array is the name of the array to be searched */ /* size is the number of elements in the array */ /* value is the value being searched for */ int binSearch(int array[], int size, int value) { int midpt, index = -1; /* index = -1 means not found */ /* first is the left-most index of the array or sub-array being searched */ /* last is the right-most index of the array or sub-array being searched */ int first = 0, last = size – 1; while ((first <= last) && (index == -1)) { midpt = (first+last)/2; /* integer division!! */ if (value > array[midpt]) first = midpt + 1; else if (value < array[midpt]) last = midpt – 1; else index = midpt; } /* end of while */ return index ; }