CSC 207 Grinnell College Fall, 2018
 
Algorithms and Object-Oriented Design
 

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.

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:

Programming Notes: In practice, details of a select method to find the kth largest element vary somewhat, based on the implementation language.