【问题标题】:Python: setting recursion limit slows sorting programPython:设置递归限制减慢排序程序
【发布时间】:2021-03-16 09:40:24
【问题描述】:

我正在做一个程序,比较不同的排序算法:插入排序、冒泡排序和快速排序。当输入是至少包含 1000 个元素的列表时,程序会抛出错误。

  File "/Users/karol/PycharmProjects/Algorytmy6/main.py", line 52, in quickSort
return quickSort(less) + equal + quickSort(greater)
  [Previous line repeated 995 more times]
  File "/Users/karol/PycharmProjects/Algorytmy6/main.py", line 43, in quickSort
    if len(list) > 1:
RecursionError: maximum recursion depth exceeded while calling a Python object

我尝试通过sys.setrecursionlimit(sizeOfList+1) 设置递归限制,但它大大减慢了快速排序算法。例如对于列表中的 10 000 个元素,快速排序比插入排序慢:

对包含 10000 个元素的列表进行排序的插入次数:3.238

对 10000 个元素的列表进行冒泡排序耗时:5.618 秒

对 10000 个元素的列表进行快速排序耗时:4.239 秒

此外,如果我只运行 quickSort 算法而不运行 insertSort 和 bubbleSort,那么它可以正常工作。而且它应该是最快的:

快速排序 10000 个元素的列表耗时:0.077 秒

我需要真正的快速排序时间,因为该程序是用来与其他排序算法进行比较的。

这是我的代码:

import random, time

def insertionSort(list):
    startTime = time.time()
    for i in range(len(list)):
        min = list[i]
        for j in range(i, len(list)):
            if list[j] <= min:
                min = list[j]
                index = j
        list[index] = list[i]
        list[i] = min

    elapsedTime = round(time.time() - startTime, 3)
    print("Insertion sorting a list of {} elements took: {} s".format(len(list), elapsedTime))

    return list

def bubbleSort(list):
    startTime = time.time()
    n = len(list) - 1
    for j in range(len(list)):
        for i in range(n-j):
            if list[i] > list[i+1]:
                temp = list[i]
                list[i] = list[i+1]
                list[i+1] = temp


    elapsedTime = round(time.time() - startTime, 3)
    print("Bubble sorting a list of {} elements took: {} s".format(len(list), elapsedTime))

    return list

def quickSort(list):

    less = []
    equal = []
    greater = []

    if len(list) > 1:
        pivot = list[0]
        for x in list:
            if x < pivot:
                less.append(x)
            elif x == pivot:
                equal.append(x)
            elif x > pivot:
                greater.append(x)
        return quickSort(less) + equal + quickSort(greater)
    else:
        return list


size = 10000
list = [0]*size

for i in range(size):
    list[i] = random.randint(1, size)

insertionSort(list)
bubbleSort(list)
startTime = time.time()
quickSort(list)
elapsedTime = round(time.time() - startTime, 3)
print("Quick sorting a list of {} elements took: {} s".format(len(list), elapsedTime))

【问题讨论】:

  • 您的支点选择很糟糕。当您的枢轴选择很糟糕时,就会发生这种情况。
  • 您还改变了两种类型的输入。
  • 众所周知,快速排序在排序列表上比在随机打乱列表上慢得多。尝试在列表的副本而不是原始列表上调用 insertionSortbubbleSort,以便原始列表保持未排序状态。请注意,您应该永远不要在python中调用列表list,因为list是整个类的名称list;隐藏该名称会引起麻烦。而是致电您的名单myList。您可以使用myList[:]list(myList) 进行复制;将 insertionSort(myList) 替换为 insertionSort(list(myList)) 以在副本而不是原始文件上运行插入排序。
  • "另外,如果我注释了 insertSort 和 bubbleSort,quickSort 就不再需要递归限制了。"嗯,什么?
  • @user2357112supportsMonica 我将枢轴选择更改为随机,我不知道它如此重要。现在程序可以正常工作了,谢谢。如何改变输入?

标签: python sorting recursion quicksort


【解决方案1】:

问题是您在前两种排序中对列表进行排序,因此当它到达快速排序时它已经排序

insertionSort(lst)
bubbleSort(lst)
quickSort(lst)

对同一个列表进行 3 次排序,但它在第一次插入排序之后已经排序。

您需要从原始顺序复制列表排序。

import copy

lst_b = copy.deepcopy(lst)
lst_q = copy.deepcopy(lst)

insertionSort(lst)
bubbleSort(lst_b)
quickSort(lst_q)

您在原始代码中看到 quickSort 问题的原因是,当列表已经排序时,排序列表会导致二次时间。

【讨论】:

    猜你喜欢
    • 2016-04-14
    • 2022-01-17
    • 2015-08-13
    • 2023-01-27
    • 2020-03-25
    • 2013-03-15
    • 1970-01-01
    • 2013-12-02
    • 2017-04-28
    相关资源
    最近更新 更多