Reputation: 41
The program is for quick sort with duplicate keys.The code runs perfectly once or twice and then gives the IndexError next time eventhough the list is not empty.When I print the indices they lie within range.Is it a problem with my computer specifically?
EDIT-added the traceback
import random
def partition(n,lo,hi):
i=lo
lt=lo #index showing the start of all duplicate partitioning keys
gt=hi #index showing the end of all duplicate partitioning keys
x=n[lt]
while(i<=gt):
while(n[i]<=n[lt] and i<=gt):
if(x!=n[lt]):
print("alert!!!")
if(n[i]<n[lt]): #current alement not a duplicate of partitioning alement
if(lt<=i):
n[lt],n[i]=n[i],n[lt]
#print(n)
i+=1
lt+=1
else: #current element is a duplicate partitioning alement
#print(n[i],"=",n[lt])
i+=1
while(n[gt]>n[lt] and i<=gt):
gt-=1
if(i<gt):
n[i],n[gt]=n[gt],n[i]
gt-=1
#print(n)
return gt
def quickSort(n,lo,hi):
#print("called")
if(lo<hi):
print(n)
p=partition(n, lo, hi)
quickSort(n, lo, p-1)
quickSort(n, p+1, hi)
def main():
nums=[]
for i in range(30):
nums.append(random.randrange(100))
print("original array")
print(nums)
k=4
hi=len(nums)-1
#print(k,"th lowest number is ",quickSelect(nums, 0,hi,k))
print(nums)
quickSort(nums,0,hi)
print(nums)
if __name__ == "__main__":
main()
Traceback:
Traceback (most recent call last):
File "C:\Users\S.reddy\workspace\sorter\src\selector\quickSelect.py", line 59, in <module>
main()
File "C:\Users\S.reddy\workspace\sorter\src\selector\quickSelect.py", line 55, in main
quickSort(nums,0,hi)
File "C:\Users\S.reddy\workspace\sorter\src\selector\quickSelect.py", line 43, in quickSort
quickSort(n, p+1, hi)
File "C:\Users\S.reddy\workspace\sorter\src\selector\quickSelect.py", line 41, in quickSort
p=partition(n, lo, hi)
File "C:\Users\S.reddy\workspace\sorter\src\selector\quickSelect.py", line 11, in partition
while(n[i]<=n[lt] and i<=gt):
IndexError: list index out of range
Upvotes: 0
Views: 773
Reputation: 104842
Your code was sometimes getting out of bounds indexes because of the order you were checking your conditions in your inner while
loop.
Often an easy best way to debug issues like this is to add try
and except
blocks to the code, with the except
block printing out useful diagnostic values. I used this variation on your loop to figure out the issue:
try:
while(n[i]<=n[lt] and i<=gt):
if(x!=n[lt]):
print("alert!!!")
if(n[i]<n[lt]): #current alement not a duplicate of partitioning alement
if(lt<=i):
n[lt],n[i]=n[i],n[lt]
#print(n)
i+=1
lt+=1
else: #current element is a duplicate partitioning alement
#print(n[i],"=",n[lt])
i+=1
except IndexError:
print(i, gt, len(n))
raise
You'll see that under certain circumstances, gt
will be len(n) - 1
and i
will be len(n)
. In that situation, the first test in while(n[i]<=n[lt] and i<=gt):
will raise an IndexError
since n[i]
is not a valid index.
Instead, you should put the tests in the other order, with the i <= gt
first. If that test is False
, the and
will "short-circuit" and not evaluate the second test, which is the one that would cause the exception. So: use while i <= gt and n[i] <= n[lt]:
(The parentheses were unnecessary, so I've removed them and spaced out the terms from the operators. See PEP 8 for more recommendations on Python style.)
Upvotes: 1
Reputation: 2046
The problem is in row 11:
while(n[i]<=n[lt] and i<=gt):
you need to change it to:
while(i<=gt and n[i]<=n[lt]):
because python first checks first condition (in this case it is i<=gt) and if it is true than he checks the second one (n[i]<=n[lt]) but if the first condition is false then python exits while loop without checking second condition.
Upvotes: 0