# algorithms.py # Walker M. White (wmw2), Lillian Lee (LJL2), Steve Marschner (srm2) # Apr 3, 2013 """ Module with algorithms from the sequence algorithm design slides.""" import cunittest2 def qsort(b, h, k): """Quick Sort: sorts the array b[h..k] in n log n average time Precondition: b is a mutable sequence (e.g. a list). h and k are valid positions in b, k >= h-1.""" if k=x. Precondition: b is a mutable sequence (e.g. a list). k>=h are both valid indices in b.""" # position i contains the pivot value, we have nothing in b[h..i-1] i = h; x = b[i] # position j is beginning of second partition range, which is currently empty j = k + 1 # invariant: b[h..i-1] <= x, b[i] = x, b[i+1..j-1] unknown, and b[j..k] >= x while i < j-1: # still have unknowns left if b[i+1] >= x: # move second partition range left by one b[i+1], b[j-1] = b[j-1], b[i+1] j = j - 1 else: # move first partition range right by one and update i b[i], b[i+1] = b[i+1], b[i] i = i + 1 # post: b[h..i-1] <= x, b[i] is x, and b[i+1..k] >= x return i def dnf(b, h, k): """Dutch National Flag algorithm to arrange the elements of b[h..k] Returns: partition points as a tuple (i,j) Precondition: b is a mutable sequence (e.g. a list). h and k are valid positions in b, k>=h-1.""" # Loop variables to satisfy the invariant t = h j = k i= k+1 # inv: b[h..t-1] < 0, b[t..i-1] unknown, b[i..j] = 0, and b[j+1..k] > 0 while t < i: if b[i-1] < 0: b[i-1], b[t] = b[t], b[i-1] t = t+1 elif b[i-1] == 0: i = i-1 else: b[i-1], b[j] = b[j], b[i-1] i = i-1 j = j-1 # post: b[h..i-1] < 0, b[i..j] = 0, and b[j+1..k] > 0 # Return dividers as a tuple return (i, j) if __name__ == '__main__': list1 = [3, 5, 0, 4, -1, 6, 2, 0, 3, 8, -1] list2 = [9,8,7,2,0,-1,-3,-7, 0] #test partition for mylist in [list1[:], list2[:], [7,1], [7,8], [0]]: print 'mylist before partition:', mylist j = partition(mylist,0,len(mylist)-1) print "after partition, pivot index is:", j, ", mylist is", mylist for k in range(j): # verify first partition range cunittest2.assert_true(mylist[k] <= mylist[j]) for k in range(j+1, len(mylist)): # verify second partition range cunittest2.assert_true(mylist[k] >= mylist[j]) print 'tests of partition passed' # test qsort # use separate loop, since sort and partition change the lists for mylist in [list1[:], list2[:], [7,1], [7,8], [0], []]: copylist = mylist[:] qsort(mylist, 0, len(mylist)-1) copylist.sort() cunittest2.assert_equals(copylist, mylist) # # inv: for indices i in 1..k-1, mylist[i-1] >= mylist[i] # for k in range(1, len(mylist)-1): # cunittest2.assert_true(mylist[k-1] <= mylist[k]) print 'test of qsort passed' #test dnf for mylist in [list1[:], list2[:], [7,1], [7,-8], [0], []]: print 'mylist before dnf', mylist (i,j) = dnf(mylist, 0, len(mylist)-1) print 'mylist after dnf',mylist for k in range(i): cunittest2.assert_true(mylist[k]<0) for k in range(i,j+1): cunittest2.assert_true(mylist[k]==0) for k in range(j+1,len(mylist)): cunittest2.assert_true(mylist[k]>0) print 'test of dnf passed' print 'Everything is OK'