0

I have small python code that implements the quickselect discussed here.

import random
def Quickselect(A, k):
    if not A:
        return
    pivot = random.choice(A)

    i = 0
    A1 = []
    A2 = [] # Two new arrays A1, A2 to store the split lists
    for i in range(len(A)):
        if A[i] < pivot :
            A1.append(A[i])
        else:
            A2.append(A[i])

    if k < len(A1):
        return Quickselect(A1, k)
    if k > len(A) - len(A2):
        return Quickselect(A2, k-(len(A) - len(A2)))
    else:
        return pivot
pass
def main():
    A = [45,1,27,56,12,56,88]
    print(Quickselect(A,2))
pass

I seem to be getting an randrange error. Is something amiss?

Edit: Implemented random.choice instead of random.randint. The above code seems to work fine. Thanks to User Blender.

Community
  • 1
  • 1
Ashwin Krishnamurthy
  • 3,750
  • 3
  • 27
  • 49

1 Answers1

1

Your error occurs because randrange breaks when the range is empty (i.e. randrange(1, 1)).

Use random.choice instead and change k <= len(A1) to k < len(A1):

def quick_select(A, k):
    pivot = random.choice(A)

    A1 = []
    A2 = []

    for i in A:
        if i < pivot:
            A1.append(i)
        elif i > pivot:
            A2.append(i)
        else:
            pass  # Do nothing

    if k <= len(A1):
        return Quickselect(A1, k)
    elif k > len(A) - len(A2):
        return Quickselect(A2, k - (len(A) - len(A2)))
    else:
        return pivot
Blender
  • 289,723
  • 53
  • 439
  • 496
  • @AshwinGanesh: `random.choice()` selects a random element from your list. Take a look at how I implemented it in my code. – Blender Feb 02 '13 at 07:34
  • @Blender thank you for pointing out the error. My question is: how do you know it's supposed to be `k < len(A1)`? Does that mean the author of the page [http://www.cs.yale.edu/homes/aspnes/pinewiki/QuickSelect.html] got it wrong? Thank you. – user1330974 Nov 20 '15 at 00:50
  • @user1330974: My bad, it should be `<=`. – Blender Nov 21 '15 at 03:06
  • @Blender, thanks for the follow-up. But if we try running that with `<=`, we get stackoverflow... – user1330974 Nov 21 '15 at 20:03
  • 1
    @user1330974: There was a bug in the original code. You also need to change the `else:` to `elif i > pivot`, as in the webpage. – Blender Nov 21 '15 at 23:45
  • @Blender Thank you. :) Didn't realize that adding `elif` and `else` would make the `<=` also work. I don't know how to really trace these recursive algorithms. If you have suggestions on effective way to track/debug them, please let me know. Otherwise, thanks a bunch for the help. :) – user1330974 Nov 22 '15 at 04:15