Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使合并排序更有效_Python_Sorting_Mergesort - Fatal编程技术网

Python 使合并排序更有效

Python 使合并排序更有效,python,sorting,mergesort,Python,Sorting,Mergesort,我正在处理一个黑客银行问题: 并用Python编写了MergeSort的实现。该算法运行良好,但我在一些较大的输入测试中遇到超时错误。由于我不是Python专家,有谁能建议我如何使代码更高效 unsorted = map(int, unsorted) # Unsorted is provided as an input, an array of strings def mergeSort(list): s = len(list) if s == 1: ret

我正在处理一个黑客银行问题:

并用Python编写了MergeSort的实现。该算法运行良好,但我在一些较大的输入测试中遇到超时错误。由于我不是Python专家,有谁能建议我如何使代码更高效

unsorted = map(int, unsorted) # Unsorted is provided as an input, an array of strings


def mergeSort(list):
    s = len(list)

    if s == 1:
        return list

    if s == 2:
        if list[0] < list[1]:
            return list
        return [list[1], list[0]]

    listA = mergeSort(list[:s / 2])
    listB = mergeSort(list[s / 2:])

    r = []

    while len(listA) > 0 or len(listB) > 0:
        if len(listA) == 0:
            r = r + listB
            return r

        if len(listB) == 0:
            r = r + listA
            return r

        if listA[0] < listB[0]:
            r.append(listA.pop(0))
        else:
            r.append(listB.pop(0))


list = mergeSort(unsorted)
for n in list:
    print n
unsorted=map(int,unsorted)#unsorted作为输入提供,是一个字符串数组
def合并排序(列表):
s=len(列表)
如果s==1:
返回列表
如果s==2:
如果列表[0]<列表[1]:
返回列表
返回[列表[1],列表[0]]
listA=mergeSort(列表[:s/2])
listB=合并排序(列表[s/2:]
r=[]
当len(listA)>0或len(listB)>0时:
如果len(listA)==0:
r=r+listB
返回r
如果len(listB)==0:
r=r+listA
返回r
如果listA[0]
根据1到10000之间100000个随机数的列表运行脚本时,我会得到以下分析结果:

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    3.687    3.687 <string>:1(<module>)
 131071/1    1.457    0.000    3.687    3.687 \Test\untitled4.py:8(mergeSort)
  1502009    1.903    0.000    1.903    0.000 {method 'pop' of 'list' objects}
  4833703    0.217    0.000    0.217    0.000 {len}
  1502009    0.110    0.000    0.110    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
ncalls tottime percall cumtime percall文件名:lineno(函数)
1    0.000    0.000    3.687    3.687 :1()
131071/1 1.457 0.000 3.687 3.687\Test\untitle4.py:8(合并排序)
1502009 1.903 0.000 1.903 0.000{“列表”对象的“pop”方法}
4833703 0.217 0.000 0.217 0.000{len}
1502009 0.110 0.000 0.110 0.000{“列表”对象的“附加”方法}
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}
从中可以看出,大部分时间都花在
pop()
len()
和函数调用上。例如,可以使用较低的指针消除
pop(0)
。 关于python中mergesort算法的类似优化有很多问题,因此请尝试应用类似问题下的答案中描述的优化

  • 通过切片不断复制子列表(例如。
    列表[:s/2]
    )使用的内存比您在 已实现合并排序以运行“”
  • 可能是合并排序太慢了,有些算法在有一些限制的情况下会运行得更快,比如和

  • 其他人也做过类似的挑战:

    对于这个挑战,字符串没有前导零,将被视为整数。长字符串大于短字符串。首先需要进行长度比较,只有当长度相等时,才应比较字符串

    通过一次性分配辅助数组aux=[none]*n,可以进一步改进这一点,其中n是行数(main()需要计算行数并将n作为参数传递给sort函数)。如果使用自上而下的合并排序,可以使用一对相互递归的函数来避免复制数据(在本例中,我假设“数据”实际上相当于指向字符串的指针数组,并且字符串永远不会被排序移动)。一个函数以原始数组中的已排序子数组结束,另一个函数以辅助数组中的已排序子数组结束。每个函数调用另一个函数两次,一次用于左半部分,一次用于右半部分,然后合并两个半部分。在特殊情况下,排序后的数据将在辅助数组中结束,且大小为1,则将单个元素从原始数组复制到辅助数组

    自底向上的合并排序要快一点,因为它跳过了用于生成n-1对索引的所有递归,首先将n个元素的数组视为每个元素的n个子数组,然后使用迭代操作索引。这并没有快很多,因为大部分时间都花在合并函数上,而合并函数对于自顶向下和自底向上的合并排序都是相同的。与优化的自上而下合并排序类似,通过基于合并过程更改合并方向来避免复制。合并过程的数量根据
    n
    预先确定,如果是奇数个过程,则第一个过程可以在适当的位置交换元素对,留下偶数个合并过程,这样排序的数据将在原始数组中结束


    这个挑战似乎是要在C中实现的,因为它提供了一个C代码段。python实现的速度要慢得多。

    如果mergesort完全是错误的算法,我不会感到惊讶。我还没有看到挑战,但可能是关于
    O(1)
    排序,比如radixsort或bucketsort。您是否尝试过内置的排序代码?如果这种情况也发生了,那么用纯Python
    mergesort
    @MSeifert无法击败它-挑战在于将字符串排序到10^6个字符的长度,因此基数排序将不是最佳选择。毫不奇怪,pop(0)是罪魁祸首!