Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.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 - Fatal编程技术网

Python 实现的排序算法的性能不佳

Python 实现的排序算法的性能不佳,python,sorting,Python,Sorting,我已经实现了一些排序算法,包括插入、选择、Shell和两种合并。我发现我的工具的性能与算法4th的描述不一致。 例如,这里有两种合并排序。对包含100000个元素的列表进行排序时,Merge1大约需要0.6秒,Merge2大约需要50秒以上。但是Merge2与Algorithms4th中的几乎相同,只是我使用python。我不明白为什么Merge2这么慢,以及如何改进它。有人能帮我吗?谢谢 第1类: def mergeself,a,b: i=0;j=0 res=[] 而i

我已经实现了一些排序算法,包括插入、选择、Shell和两种合并。我发现我的工具的性能与算法4th的描述不一致。 例如,这里有两种合并排序。对包含100000个元素的列表进行排序时,Merge1大约需要0.6秒,Merge2大约需要50秒以上。但是Merge2与Algorithms4th中的几乎相同,只是我使用python。我不明白为什么Merge2这么慢,以及如何改进它。有人能帮我吗?谢谢

第1类: def mergeself,a,b: i=0;j=0 res=[] 而ihi: 源[k]=辅助[i] i=i+1 elif aux[i]源[i+1]: 返回错误 返回真值 以下是算法中的实现:

以下是测试代码:

merge1=merge1 source=np.random.randint100000,size=100000.tolist 开始=时间 merge1.sortsource 结束=时间 printMerge1接受:{}s.formatend-start merge2=merge2 source=np.random.randint100000,size=100000.tolist 开始=时间 merge2.sortsource 结束=时间 printMerge2接受:{}s.formatend-start 结果: E:>python sort.py 合并1需要:0.6376256942749023s
Merge2需要:57.99568271636963s

考虑此修改。根据我的快速测试,它大大提高了性能,从近一分钟下降到不到1秒。主要的性能增益来自于避免创建整个列表的那么多副本。其他改动只能略微提高性能。 根据一个简单的总和比较,它不应该弄乱列表,但是如果你想使用它,你应该做更多的测试

class Merge4:
    def merge(self, source, aux, lo, mid ,hi):
        i = lo
        j = mid + 1
        a_j= aux[j]
        a_i= aux[i]
        k = lo
        while k <= hi:
            if i > mid:
                source[k] = a_j
                j += 1
                a_j= aux[j]
            elif j > hi:
                source[k] = a_i
                i += 1
                a_i= aux[i]
            elif a_i < a_j:
                source[k] = a_i
                i += 1
                a_i= aux[i]
            else:
                source[k] = a_j
                j += 1
                a_j= aux[j]
            k += 1
        # update the aux array for the next call
        aux[lo:hi+1]= source[lo:hi+1]

    def sort(self, source):
        sz = 1
        N = len(source)
        while sz < N:
            sz_2= sz * 2
            # create the aux array, that will be maintained continuously
            # and add one extra None, so the "prefetching" works also
            # during the last iteration (refering to a_i and a_j)
            aux= source[:]
            aux.append(None)
            for lo in range(0, N-sz, sz_2):
                # pdb.set_trace()
                self.merge(source, aux, lo, lo+sz-1, min(lo+sz_2-1, N-1))
            sz = sz_2

    def is_sort(self, source):
        length = len(source)
        for i in range(0, length-1):
            if source[i] > source[i+1]:
                return False
        return True

在不深入讨论算法细节的情况下,最突出的是Merge1只是用append构造一个列表,而Merge2一次修改一个现有列表中的一个元素,同时更频繁地访问列表进行比较——我认为这是解释的主要部分。与Merge1相比,Merge2看起来并不是很乐观。有一件事我突然想到了。在merge2中,aux始终填充整个阵列的一个副本,尽管该副本的实际使用范围很小。这可能会产生大量的复制和垃圾收集开销。也许你可以考虑在整个手术过程中保持一个完整的拷贝。