1

I was trying to write the QuickSort algorithm using the Hoare Partition Scheme. I'm pretty sure my Partition function is correct. I use a variable 'Swaps' to indicate the movement of the left pivot towards the right and the movement of the right pivot towards the left. The Sort function works with the other Partition algorithm so I think that's fine as well. Yet I get the error.

inp=[2,3,6,3,9,7,8,0,5]

#Swap Function
def Swap(List, i, j):
    temp=List[i]
    List[i]=List[j]
    List[j]=temp


#QuickSort Function
def QSort(List, Start, End):
    if Start < End:

        PIEnd=Partition(List, Start, End)

        QSort(List,Start,PIEnd)
        QSort(List,PIEnd+1,End)

    return List



#Partition Function
def Partition (List, Start, End):
    Swaps=0
    PIStart=Start #PI = Pivot Index
    PIEnd=End 

    for i in range(Start, End):
        if List[PIStart] > List[PIEnd]:
            Swap(List, PIStart, PIEnd)
            Swaps=Swaps+1       
        if Swaps % 2 ==0:
            PIStart=PIStart+1
        else:
            PIEnd=PIEnd-1

    return PIEnd

print(QSort(inp, 0, 8))
shailesh
  • 43
  • 1
  • 7

1 Answers1

1

Look in these two places ...

# QSort ...
        PIEnd=Partition(List, Start, End)

        QSort(List,Start,PIEnd)
        QSort(List,PIEnd+1,End)

# Partition
        if Swaps % 2 ==0:
            PIStart=PIStart+1
        else:
            PIEnd=PIEnd-1

If you have an even quantity of swaps in any partition, then PIEnd will not change, and your indirect recursion in QSort will stick on the same arguments. Your first low-half recursion does this. Revisit your logic. For starters, you should not depend on global variables for a solution.

Here's how I instrumented your code for a recursion trace:

call_count = 0
indent = ""


#QuickSort Function
def QSort(List, Start, End):
    global call_count, indent
    indent += "  "
    call_count += 1
    print(indent, "ENTER QSort", Start, End, List)

    if call_count > 2 * len(inp):
        print(indent, "Too many calls")
        exit(1)

    if Start < End:

        PIEnd=Partition(List, Start, End)

        QSort(List,Start,PIEnd)
        QSort(List,PIEnd+1,End)

    print(indent, "ENTER QSort", Start, End, List)    
    indent = indent[2:]

    return List

Output:

   ENTER QSort 0 8 [2, 3, 6, 3, 9, 7, 8, 0, 5]
     ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
       ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
         ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
           ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
             ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
               ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                 ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                   ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                     ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                       ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                         ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                           ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                             ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                               ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                                 ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                                   ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                                     ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                                       ENTER QSort 0 4 [2, 3, 0, 3, 5, 7, 8, 9, 6]
                                       Too many calls
Prune
  • 76,765
  • 14
  • 60
  • 81
  • This is one of the best answers I could have got. My algorithm although statrted working when I changed the first recursion call from start to PIEnd-1. I thought that if there was a partition with 0 swaps, I would get the same error but I got no error is an already sorted list. I am even more puzzled as to why the error disappeared. – shailesh Apr 27 '20 at 13:14
  • 1
    If you're puzzled, put in a few strategic `print` statements to trace the values and calls. This is a critical skill in programming -- adding code to change your own mind about how the program *really* works. I know this from loooooong experience. – Prune Apr 27 '20 at 15:15