I am writing a program meant to find the average number of recursive calls it takes to run quickselect, and I have added a counter "calls" to keep track of the number of recursive calls. I have it incrementing every time quickselect is called again, but when I use a larger number for main the number of calls quickly goes into exponential territory. I would like for main to return the average number of calls, and I know the number I am getting is wrong but I cannot tell why. Any suggestions would be welcomed.
import numpy
import numpy as np
import random
def main(trials,k):
i = 0;
hold = []
calls = -1;
while i < trials:
generate(hold, 75)
calls = calls + quickselect(hold, k, calls)
i = i + 1
print(calls/trials)
def generate(l,n):
for i in range(n):
r=random.randint(0,n)
if r not in l:
l.append(r)
def quickselect(l, k, calls) :
#l is the list of the numbers
#we are finding the kth largest element
calls = calls + 1
length = len(l)
pivotselect = numpy.random.randint(0,length,1)
l = numpy.array(l)
#print(pivotselect)
#print(l[pivotselect])
pivot = l[pivotselect]
#print("this is the pivot", pivot)
# Pick a random pivot element from the list, each
# equally likely
l_small = []
l_big = []
smalltrack = 0
bigtrack = 0
i = 0
ispivot = 0
while i < length:
#print(i)
compare = l[i]
if compare < pivot:
l_small.append(compare)
smalltrack = smalltrack + 1
#print(l_small)
elif l[i] > pivot:
l_big.append(compare)
bigtrack = bigtrack + 1
else:
ispivot = ispivot + 1
#print(compare, "ispivot is now", ispivot)
i = i + 1
#print("ispivot is", ispivot)
#print(len(l_small), "small then big", len(l_big))
checker = len(l_small) + len(l_big)
#print(checker)
checker = checker + ispivot
#print(checker)
assert(length == checker)
l_big = numpy.array(l_big)
l_small = numpy.array(l_small)
#print("check 1")
if k <= len(l_big):
# kth largest must be in l_big
res = quickselect(l_big, k, calls)
#print("check 2")
#calls = calls + 1
return res
elif k > len(l_big) + 1:
# kth largest must be in l_small
res = quickselect(l_small, k - len(l_big) - 1, calls)
#print("check 3")
#calls = calls + 1
return res
else:
#print("check 4")
#print("calls", calls)
print(calls)
return calls
As your code is written, you are more than doubling
calls
each time you callquickselect
. You're passing it the current value, incrementing it by however many timesquickselect
is called, and then adding that new value ofcalls
to your old value.You need to get rid of either one addition or the other. You can either:
Call
quickselect
inmain
with the calls argument being 0. Continue to add the return result tocalls
.You can just call
quickselect(hold, k, calls)
and not add the return value tocalls
.