/* Mergesort, as developed in lecture * Frank Pfenning, Fall 2010 * see mergesort-invs.c0 for a version with stronger invariants */ bool is_sorted(int[] A, int lower, int upper) //@requires 0 <= lower && lower <= upper && upper <= \length(A); { int i; for (i = lower; i < upper-1; i++) //@loop_invariant lower == upper || (lower <= i && i <= upper-1); if (!(A[i] <= A[i+1])) return false; return true; } /* merge(A, lower, mid, upper) merges two adjacent sorted * segments A[lower..mid) and A[mid..upper) into A[lower..upper) */ void merge(int[] A, int lower, int mid, int upper) //@requires 0 <= lower && lower < mid && mid < upper && upper <= \length(A); //@requires is_sorted(A, lower, mid) && is_sorted(A, mid, upper); //@ensures is_sorted(A, lower, upper); { int[] B = alloc_array(int, upper-lower); int i = lower; int j = mid; int k = 0; while (i < mid && j < upper) //@loop_invariant lower <= i && i <= mid; //@loop_invariant mid <= j && j <= upper; //@loop_invariant k == (i-lower)+(j-mid); { if (A[i] <= A[j]) { B[k] = A[i]; i++; } else { B[k] = A[j]; j++; } k++; } //@assert i == mid || j == upper; while (i < mid) //@loop_invariant lower <= i && i <= mid; //@loop_invariant k == (i-lower)+(j-mid); { B[k] = A[i]; i++; k++; } while (j < upper) //@loop_invariant mid <= j && j <= upper; //@loop_invariant k == (i-lower)+(j-mid); { B[k] = A[j]; j++; k++; } for (k = 0; k < upper-lower; k++) //@loop_invariant lower <= lower+k && lower+k <= upper; A[lower+k] = B[k]; } void mergesort (int[] A, int lower, int upper) //@requires 0 <= lower && lower <= upper && upper <= \length(A); // modifies A; //@ensures is_sorted(A, lower, upper); { if (upper-lower <= 1) return; else { int mid = lower + (upper-lower)/2; mergesort(A, lower, mid); //@assert is_sorted(A, lower, mid); mergesort(A, mid, upper); //@assert is_sorted(A, mid, upper); merge(A, lower, mid, upper); } }