CS 415, Section 002 Sonoma State University Spring, 2022
 
Algorithm Analysis
Instructor: Henry M. Walker

Lecturer, Sonoma State University
Professor Emeritus of Computer Science and Mathematics, Grinnell College

Lab:  Pictoral Loop Invariants

Goals

This laboratory exercise applies the concept of loop invariants to problems involving array structures.

Partitions, Medians, and Quicksort

Several useful applications utilize a function

   int partition (int a[], int left, int right)

This function rearranges the elements of a between a[left] and a[right], so that one array element has moved to the place it would belong in a sorted array. That is, the array elements are permuted to achieve the property described by the following array picture:

Partition Problem 1

As suggested by this picture, partition moves an element of a to a position a[middle] and rearranges the remainder of the array segment a[left] ... a[right], so that

As it finishes, function partition returns the final value of middle.

Thus, the array segment a[left] ... a[right] is rearranged as required, to give a new arrangement of values a[left] ... a[(middle)] ... a[right], where all array elements before position middle have values <= a[(middle)] and where a[(middle)] is less than or equal to all array elements after position middle.

In its simplest form, the designated element within partition begins at a[left]. To accomplish the final arrangement shown above, we develop a loop that maintains the following picture:

Partition Problem 2

To clarify this diagram, the variable r_spot gives the location, so that a[r_spot+1], ..., a[right] are all >= a[left], and a[left+1], ..., a[l_spot-1] are all <= a[left].

The main work in partition is to narrow the array segment in the middle of the above diagram, until there are no elements left in the middle. The main idea is to move r_spot to the left to find a small element and l_spot to the right to find a large element. Then we can swap the elements at positions l_spot and r_spot to expand the array segments for the small and large elements. Once the middle section has been eliminated, we swap a[left] and a[r_spot] to obtain the diagram at the beginning of this lab.

Adding some detail, partition proceeds with single pass through the elements a[left] ... a[right], as follow:

  1. move left in the array through a[right], a[right-1], ... until finding an element a[r_spot] where a[r_spot] < a[left], if such an element exists.

  2. move right in the array through a[left], a[left+1], ... until finding an element a[l_spot] where a[l_spot] > a[left], if such an element exists.

  3. swap a[l_spot] and a[r_spot].

  4. continue steps a, b, and c until searching all elements in the array segment. (At this point, "small" values will have been moved early within the array segment, while "large" values will have been moved late.)

  5. place a[left] in its appropriate position a[middle], where middle is the index where l_spot and r_spot have come together.

The first work for this lab asks you to implement partition.

  1. Use the in-progress diagram above to determine the exit condition for your loop, and explain why this condition is correct.

  2. Write the partition code based on this diagram, and test it with several cases. In submiting the lab, include the partition code, the enclosing program used for testing, and a print out of the test cases/runs used to check correctness.

Finding Median Values:

The partition method may be used to find the kth smallest element in an array involves narrowing the range to be examined within the overall array using the partition method. For example, suppose that partition returns index middle as the location of the final location for the pivot. Basic processing involves three cases:

  1. Write a procedure select that uses the above algorithm and procedure partition to find the kth smallest element in an array a. Your lab write up should include the code for select, the enclosing program used for testing, and the test runs used for checking correctness.

  2. Write a procedure median uses the above algorithm and procedures partition and/or select.to find the median element in an array. Your lab write up should include the code for median, the enclosing program used for testing, and the test runs used for checking correctness.

Quicksort:

The quicksort algorithm proceeds by applying partition recursively, until all subintervals have no more than a single element (and thus are already sorted).

  1. Write a quicksort procedure that uses the partition procedure and sorts the array a using the quicksort algorithm.

    Include your quicksort procedure in an appropriate test program, so that you can adequately check the correctness of your code.

    Programming Notes: As with the Select method, in practice, the procedure header for quicksort and some coding elements depend upon the programming language being utilized.

Dutch National Flag Problem

The Dutch National Flag Problem was first proposed by W.H.J. Feijen and made famous by Edsger W. Dijkstra. The following formulation relates the problem to arrays in C.

Enumerations in C are described in Kernighan and Ritchie, Section 2.3, page 39. For example, an enumeration with three colors could be declared as:

   enum color { red, white, blue };

and we may consider an array of colors:

   #define size 50 /* number of elements in an array */
   color colors [size];
Color Array

When we begin, we do not know the number of elements of each color, and we are not even assured that each color is actually present.

The Dutch National Flag Problem seeks to sort this array, so that red's come first, then white's, and then blue's. Movement of array elements may be accomplished only by swapping two items.

Sorted Color Array

Solution

Although one approach to this problem involves simple sorting (just consider red < white < blue), the problem can be solved in a single pass of the data. The idea is to identify an array diagram that describes sections of colors as loop invariants. Writing the code then is reasonably straightforward; we just have to maintain the invariant!

For this problem, at least four different pictorial loop invariants initially come to mind:

Possible Loop Invariants

In each case, we must introduce variables to keep track of the edge of the red, white, and blue sections. Initially, these sections contain no elements, and the entire array is unprocessed. Then as processing proceeds, the program looks at successive unprocessed elements and puts them in their correct locations — maintaining the loop invariant.

  1. For two of these pictorial loop invariants, introduce variables to record the index of a boundary between colors, and describe the invariant carefully in words. Then add the variables to the pictorial loop invariants. Check with your instructor before continuing!

In what follows you will create two loop segments to solve the Dutch National Flag Problem, one segment for each invariant you have identified above.

  1. For each of the two approaches, initialize your variables, so that the pictorial loop invariants are satisfied at the start of processing.

  2. Complete the loop processing, maintaining the identified loop invariant.

  3. Test your program with several test runs.


created 20 April 2008
revised 24 January 2009
revised December-January 2021
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.