I am new in Python and I exercising in writing codes, but I am having some troubles.
I am trying to implement QuickSelect in order to extract the K largest element.
This is my code;
def partition(A, left, right):
pivot = random.randrange(left, right) # pick a random number as pivot
i = left - 1
for j in range(left, right):
if A[j] <= pivot:
i = i+1
A[i], A[j] = A[j], A[i]
A[i+1], A[right] = A[right], A[i+1]
return i+1
def QuickSelect(A, K, left, right): # Array, K-th element
if left == right:
return A[left]
q = partition(A, left, right)
i = q - left + 1
if K == i:
return A[i]
if K < i:
return QuickSelect(A, K, left, q - 1)
else:
return QuickSelect(A, K - i, q + 1, right)
Trying to implement the algorithm in order to get the 5-th highest element :
a = get_random_array(10, 100)
print("array unsorted=" , a)
print("array sorted=", sorted(a))
print("result:" , QuickSelect(A = a, K = 5, left = 0, right = len(a)-1)) #I want the 5-th highest element
getting this result:
array unsorted = [71, 34, 0, 36, 26, 15, 3, 69, 93, 85]
array sorted = [0, 3, 15, 26, 34, 36, 69, 71, 85, 93]
result: 3
The result is wrong since 3 is not the 5-th highest element.
Is the error in partition(A, left, right)
or in QuickSelect(A, K, left, right)
?
Could you help me to solve it please? Thank you!
There are several issues in your code.
pivot
as a value, but it is an index.right
), before you start the loopK == i
you should not return A[i]
, as i
is a relative, 1-based index. You should return A[q]
randrange(left, right)
will never return right
, so probably you want to do randrange(left, right + 1)
or randint(left, right)
The corrected code:
def partition(A, left, right):
# This gets an index, not a value:
pivotindex = random.randint(left, right) # allow right to be selected
pivot = A[pivotindex] # this is the pivot value
# move the value out of the way
A[right], A[pivotindex] = A[pivotindex], A[right]
i = left - 1
for j in range(left, right):
if A[j] < pivot:
i += 1
A[i], A[j] = A[j], A[i]
A[i+1], A[right] = A[right], A[i+1]
return i + 1
def QuickSelect(A, K, left, right):
if left == right:
return A[left]
q = partition(A, left, right)
i = q - left + 1
if K == i:
return A[q] # this is the element you want to return
if K < i:
return QuickSelect(A, K, left, q - 1)
else:
return QuickSelect(A, K - i, q + 1, right)