Guest User

Gareth McCaughan

a guest
Sep 24th, 2010
233
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 1.71 KB | None | 0 0
  1. # McIlroy's quicksort adversary, against a randomized quicksort
  2.  
  3. import math,random,sys
  4. sys.setrecursionlimit(100000) # so bad qsort doesn't die
  5.  
  6. # A simple randomized quicksort.
  7. # comparator takes array and two indices (the C version takes two pointers);
  8. # it returns <0, ==0, >0 if p<q, p==q, p>q.
  9. def qsort(a, i,j, comparator):
  10.   # easy cases:
  11.   if j<=i: return
  12.   if j<=i+1:
  13.     if comparator(a,i,j)>0:
  14.       a[i],a[j] = a[j],a[i]
  15.     return
  16.   # choose a pivot at random
  17.   k = random.randint(i,j)
  18.   # partition
  19.   a[k],a[j] = a[j],a[k] # pivot to end
  20.   left=i
  21.   for l in range(i,j):
  22.     if comparator(a,l,j)<=0:
  23.       a[left],a[l] = a[l],a[left]
  24.       left += 1
  25.   a[left],a[j] = a[j],a[left]
  26.   qsort(a,i,left-1,comparator)
  27.   qsort(a,left+1,j,comparator)
  28.  
  29. def good_tester(n):
  30.   a = [random.random() for i in range(n)]
  31.   comparisons = [0] # list hack to work around crappy scoping rules
  32.   def _(a,i,j):
  33.     comparisons[0] += 1
  34.     return a[i]-a[j]
  35.   qsort(a,0,n-1,_)
  36.   return comparisons[0]
  37.  
  38. def evil_tester(n):
  39.   gas = n-1
  40.   # nsolid,candidate,comparisons are arrays to work around crappy scoping rules
  41.   nsolid = [0]
  42.   candidate = [0]
  43.   comparisons = [0]
  44.   a = [gas for i in range(n)]
  45.   def freeze(a,i):
  46.     a[i] = nsolid[0]
  47.     nsolid[0] += 1
  48.   def _(a,i,j):
  49.     comparisons[0] += 1
  50.     if a[i]==gas and a[j]==gas:
  51.       if i==candidate[0]: freeze(a,i)
  52.       else: freeze(a,j)
  53.     if a[i]==gas: candidate[0]=i
  54.     else: candidate[0]=j
  55.     return a[i]-a[j]
  56.   qsort(a,0,n-1,_)
  57.   return comparisons[0]
  58.  
  59. print "good:"
  60. for n in (10,100,1000,10000):
  61.   m = good_tester(n)
  62.   print n, m, m/(n*math.log(n))
  63.  
  64. print "evil:"
  65. for n in (10,100,1000):
  66.   m = evil_tester(n)
  67.   print n, m, m/(n**2.)
Advertisement
Add Comment
Please, Sign In to add comment