气泡排序优于选择排序

时间:2018-08-06 18:00:01

标签: python-3.x algorithm sorting computer-science

我目前正在尝试了解排序算法,并且一直在研究伪代码并将其转换为python(使用python 3.6,IDE是Spyder 3.1.2)。我写了一个简单的冒泡排序:

def BubbleSort(array_to_sort):
    n = len(array_to_sort) - 1
    swapped = True
    while (swapped):
        swapped = False
        for i in range(n):
             if array_to_sort[i] > array_to_sort[i+1]:
                array_to_sort[i+1], array_to_sort[i] = array_to_sort[i], array_to_sort[i+1] 
                swapped = True
    return array_to_sort

和一个简单的选择排序:

def SelectionSort(array_to_sort):
    n = len(array_to_sort)
    for i in range(n):
        minPos = i
        for j in range(i+1, n):
            if array_to_sort[j] < array_to_sort[minPos]:
                minPos=j

        if minPos != i:
            array_to_sort[i], array_to_sort[minPos] = array_to_sort[minPos], array_to_sort[i] 

    return array_to_sort

并且正在尝试像这样计时他们:

def main():
    array = RandomNumberArray()
    a = timeit.Timer(functools.partial(BubbleSort, array)) 
    print(a.timeit(1000))
    b = timeit.Timer(functools.partial(SelectionSort, array)) 
    print(b.timeit(1000))

RandomNumberArray只是生成我要排序的数字列表:

def RandomNumberArray():
    return random.sample(range(0, 1000), 1000)

因为它们都具有相同的时间复杂度O(n 2 ),所以我期望它们花费的时间大致相同,但是我发现我的选择排序的性能相对较差到我的气泡排序中,例如在1000次迭代中具有1000个数字的数组-
BS结果:0.390 s
SS结果:63.618 s

以及经过10000次迭代的1000个数字的数组-
BS结果:2.074 s
SS结果:645.944 s

这些算法的实现是否存在问题,或者预计会有如此大的差异?我知道还有其他更快的排序方式,实际上没有人会真正使用BS或SS,但是我只是想了解为什么SS似乎比BS慢得多?

3 个答案:

答案 0 :(得分:6)

这是不公平的比较,因为array由第一个调用排序,然后传递到第二个调用。对于几种排序算法来说,已经排序的输入是最坏的情况。

气泡排序还具有O(n)个最佳情况时间复杂度,而选择具有O(n ^ 2)个最佳情况时间。

答案 1 :(得分:1)

@richard用户指出了主要问题。

总的来说,我希望每次编写的泡沫排序都能胜过选择排序。您的冒泡排序不是特别写得好,因为它没有利用算法在外循环每次迭代后提供的部分排序。也就是说,您有:

def BubbleSort(array_to_sort):
    n = len(array_to_sort) - 1
    swapped = True
    while (swapped):
        swapped = False
        for i in range(n):
             if array_to_sort[i] > array_to_sort[i+1]:
                array_to_sort[i+1], array_to_sort[i] = array_to_sort[i], array_to_sort[i+1] 
                swapped = True
    return array_to_sort

每次通过外循环,又有一个项目按顺序被推到数组的末尾。即,第一次通过循环,将最大项推到最后一个位置。下次,第二大的被推到倒数第二个位置,依此类推。但是您的代码没有利用这一点。而是连续比较已排序的项目。您可以使用以下方法大大改善代码:

def BubbleSort(array_to_sort):
    n = len(array_to_sort) - 1
    swapped = True
    j = 0
    while (swapped):
        swapped = False
        for i in range(0, n-j):
             if array_to_sort[i] > array_to_sort[i+1]:
                array_to_sort[i+1], array_to_sort[i] = array_to_sort[i], array_to_sort[i+1] 
                swapped = True
        ++j;
    return array_to_sort

气泡排序通常比选择排序快,这有两个原因:1)如果没有进行交换,则有一个“提前退出”功能可以让您退出。 2)参照地点要好得多;您总是在比较和交换相邻项目。

答案 2 :(得分:0)

冒泡排序的一种更有价值的优化方法是,利用迭代进行的最后一次交换使数组的末端(在该点之外)处于最终状态。例如,在第一遍中:

a = [2, 1, 3, 4, 5, 6, 7, 8, 9, 10]

只有a[0]a[1]被交换,这意味着不需要做更多的事情。第一遍已经确定a[0] < a[1] <= a[2] <= ... <= a[9]

这比swapped标志更难编码,但是更有效。请注意,此代码不会返回列表。您可能已经注意到,使对象(例如list.sort())发生突变的Python对象方法通常返回None。这是故意的,以提醒您已对对象进行了突变。否则,就像您发布的原始测试代码中一样,很容易错误地假设该函数将原始对象留在了原处。

def bubbly(a):
    n = len(a)
    while n:
        lastswap = 0
        for i in range(1, n):
            if a[i-1] > a[i]:
                a[i-1], a[i] = a[i], a[i-1]
                lastswap = i
        n = lastswap