【问题标题】:Getting Error: Maximum Recursion Depth Exceeded in Comparison出现错误:比较中超出了最大递归深度
【发布时间】:2020-08-03 07:31:25
【问题描述】:

我尝试使用 Hoare 分区方案编写快速排序算法。我很确定我的分区功能是正确的。我使用变量“交换”来指示左枢轴向右移动和右枢轴向左移动。 Sort 函数适用于其他 Partition 算法,所以我认为这也很好。然而我得到了错误。

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))

【问题讨论】:

    标签: python quicksort partitioning partition hoare-logic


    【解决方案1】:

    看看这两个地方...

    # 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
    

    如果您在 any 分区中的交换数量是偶数,那么 PIEnd 将不会改变,并且您在 QSort 中的间接递归将坚持相同的参数。您的第一个低半递归执行此操作。重新审视你的逻辑。对于初学者,您应该依赖全局变量来解决问题。

    以下是我为递归跟踪检测您的代码的方法:

    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
    

    输出:

       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
    

    【讨论】:

    • 这是我能得到的最好答案之一。当我将第一个递归调用从 start 更改为 PIEnd-1 时,我的算法虽然开始工作。我认为如果有一个有 0 个交换的分区,我会得到同样的错误,但我没有得到错误是一个已经排序的列表。我更疑惑为什么错误消失了。
    • 如果您感到困惑,请添加一些战略性的print 语句来跟踪值和调用。这是编程中的一项关键技能——添加代码以改变您对程序真正如何工作的想法。我从很长时间的经验中知道这一点。
    猜你喜欢
    • 1970-01-01
    • 2019-04-18
    • 2021-02-13
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 2016-12-10
    • 1970-01-01
    • 2018-12-03
    相关资源
    最近更新 更多