测量基数排序时出现奇怪的结果



我正在使用模块测量基数的执行时间和计数排序timeit。我正在使用位于区间 <0 上的 100 组随机整数;1000000>.所有整数在集合中都是唯一的。第一组由 10000 个整数组成,最后一组由 1000000 个整数组成。每组被排序十次,并记录平均时间(作为full time/10)。在 Radix 排序的日志文件中有一些奇怪的结果,我不确定这是timeit模块或我的排序算法的问题:

基数排序日志

integers count, average time
......,.............
760000,1.51444417528
770000,1.31519716697
780000,1.33663102559
790000,1.3484539343
800000,1.37114722616
810000,1.61706798722
820000,1.4034960851
830000,1.65582925635
840000,1.68017826977
850000,1.69828582262
860000,1.47601140561
870000,1.73875506661
880000,1.75641094733
890000,1.54894320189
900000,1.80121665926
910000,1.56070168632
920000,1.8451221867
930000,1.8612749805
940000,1.61202779665
950000,1.63757506657
960000,1.64939744866
970000,1.66534313097
980000,1.68155078196
990000,1.69781920007
1000000,2.00389959994

您可以看到,对比以前更大的集合进行排序有时花费的时间更少。在计数排序的情况下,时间正常增加。

这是我的基数排序代码:

from __future__ import division
def sortIntegerList (listToSort, base):
    maxkey = len(str(max(listToSort)))
    for i in range(maxkey):
        bucketList = [[] for x in range(base)]
        for number in listToSort:
            bucketList[(number//base**i) % base].append(number)
        listToSort = []
        for l in bucketList:
            listToSort.extend(l)
    return listToSort

这是我的计数排序代码:

def sortIntegerList (listToSort):
    maxkey = max(listToSort)
    countingList = [0 for x in range(maxkey + 1)]
    for i in listToSort:
        countingList[i] += 1
    for i in range(1, len(countingList)):
        countingList[i] += countingList[i-1]
    sortedList = [0 for x in range(len(listToSort) + 1)]
    for i in listToSort:
        sortedList[countingList[i]] = i
        countingList[i] -= 1
    del sortedList[0]
    return sortedList

以下是用于测量执行时间的代码:

import timeit
outputFileCounting = "count,timen"
outputFileRadix = "count,timen"
# Counting Sort
for x in range(10, 1001, 10):
    setup_counting = """
from sorters import counting_sort
import cPickle
with open("ri_0-1000k_{0}k.pickle", mode="rb") as f:
    integerList = cPickle.load(f)
        """.format(x)
    time_counting = timeit.timeit("""counting_sort.sortIntegerList(integerList)""",
                                setup = setup_counting, number=10)
    outputFileCounting += "{0},{1}n".format(str(x*1000), time_counting/10)
    with open("sort_integer_counting_results.csv", mode="w") as f:
        f.write(outputFileCounting)
# Radix Sort
for x in range(10, 1001, 10):
    setup_radix = """
from sorters import radix_sort
import cPickle
with open("ri_0-1000k_{0}k.pickle", mode="rb") as f:
    integerList = cPickle.load(f)
        """.format(x)
    time_radix = timeit.timeit("""radix_sort.sortIntegerList(integerList, 10)""",
                                setup = setup_radix, number=10)
    outputFileRadix += "{0},{1}n".format(str(x*1000), time_radix/10)
    with open("sort_integer_radix_results.csv", mode="w") as f:
        f.write(outputFileRadix)

每个整数集都作为列表存储在pickle文件中。

基数排序会做很多内存的分配和重新分配。我想知道,也许,这是否是问题所在。如果您只为数据结构分配一次内存,并接受需要过度分配的事实,该怎么办?

除此之外,您是否检查过以确保最终列表确实已排序?您是否查看过基数排序(即最小/最大/中位数)时间的其他统计数据,也许偶尔会有异常值,调查它们可以帮助您解释事情。

最新更新