为什么冒泡排序的实现速度明显慢于预期?

时间:2018-01-27 14:27:24

标签: python performance sorting

我实现了以下代码,但我不知道为什么我认为运行速度更快的“快速”冒泡实际运行速度比预期慢。在第一个实现中,我认为我浪费了大量时间来检查每个数组是否已经排序,这需要花费O(n)时间。但是在第二个实现中,我正在检查数组是否按照我的交换进行排序,那么为什么第二个实现的运行速度比我想象的慢呢?

分配是否比完全遍历列表需要更多时间?

def check_sorted(A):
    for i in xrange(1, len(A)):
        if A[i] < A[i-1]:
            return False

    return True

def bubble_sort(A):
    while not check_sorted(A):
        for i in xrange(1, len(A)):
            if A[i] < A[i-1]:
                A[i], A[i-1] = A[i-1], A[i]

    return A

def bubble_sort_fast(A):
    swap = True
    while swap:
        swap = False
        for i in xrange(1, len(A)):
            if A[i] < A[i-1]:
                A[i], A[i-1] = A[i-1], A[i]
                swap = True
    return A

A = list(reversed(range(5000)))
start_time = time.time()
A = bubble_sort(A)
print 'time_elapsed:', time.time() - start_time

A = list(reversed(range(5000)))
start_time = time.time()
A = bubble_sort_fast(A)
print 'time_elapsed:', time.time() - start_time


time_elapsed: 2.20229792595
time_elapsed (fast bubble sort): 2.38038301468

1 个答案:

答案 0 :(得分:1)

“快”的人正在做更多的工作。添加计数器以查看他们执行其他人未执行操作的频率:

def check_sorted(A):
    for i in xrange(1, len(A)):
        global slow_checks; slow_checks += 1              # <== Added this
        if A[i] < A[i-1]:
            return False
    return True

def bubble_sort_fast(A):
    swap = True
    while swap:
        swap = False
        for i in xrange(1, len(A)):
            if A[i] < A[i-1]:
                A[i], A[i-1] = A[i-1], A[i]
                swap = True
                global fast_marks; fast_marks += 1        # <== Added this
    return A

你会发现slow_checks最终为9998,而fast_marks最终为12497500.这还有很多。确切地说,这是5000 * 4999/2,原始数据中的交换总数。

为什么slow_checks这么小?好吧,因为从一个泡沫迭代到下一个泡泡迭代,你的列表就会像这样发展:

Start:                  [4999, 4998, 4997, 4996, 4995, ...
After bubbling 4999 up: [4998, 4997, 4996, 4995, 4994, ...
After bubbling 4998 up: [4997, 4996, 4995, 4994, 4993, ...
After bubbling 4997 up: [4996, 4995, 4994, 4993, 4992, ...
After bubbling 4996 up: [4995, 4994, 4993, 4992, 4991, ...
...
After bubbling 4 up:    [3, 2, 1, 0, 4, 5, 6, 7, 8, 9, ...
After bubbling 3 up:    [2, 1, 0, 3, 4, 5, 6, 7, 8, 9, ...
After bubbling 2 up:    [1, 0, 2, 3, 4, 5, 6, 7, 8, 9, ...
After bubbling 1 up:    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...

正如您所看到的,check_sorted在查看前两个值后始终可以return False!除了你最后一次问它,因为它会遍历整个列表并发现它已经排序。所以4999次它只进行一次检查,然后一次进行4999次检查,总计9998次检查。

我的整个代码:https://repl.it/repls/SnarlingHotpinkNatterjacktoad