在python中冒泡排序列表是否最有效?

时间:2014-01-22 01:29:59

标签: python algorithm performance bubble-sort

我正在尝试看看这是否是在python中对泡泡列表进行排序的最有效方法,或者是否有更好的方法让某些人告诉我使用两个循环,这样做的好处与下面​​的< / p>

def sort_bubble(blist):
    n = 0
    while n < len(blist) - 1:
        if blist[n] > blist[n + 1]:
            n1 = blist[n]
            n2 = blist[n + 1]
            blist[n] = n2
            blist[n + 1] = n1
            n = 0
        else:
            n = n + 1
    print blist

3 个答案:

答案 0 :(得分:3)

您的算法在技术上是一种冒泡排序,因为它完全符合它应该进行的交换。但是,它是非常低效的冒泡排序,因为它比必要的批次进行了更多的比较。

你怎么能知道那个?检测代码以计算比较和交换的数量非常容易。同时,Wikipedia使用伪代码语言实现了一个简单的冒泡排序和一个跳过排序尾部优化的实现,这种语言非常容易移植到Python和类似的工具。我会在底部显示代码。

对于完美的冒泡排序,给定一个长度为100的随机列表,您应该期望比较低于10000(100 * 100),以及低于2500交换的位。维基百科的实现确实如此。 &#34;跳过排序的尾巴&#34;版本应该只有一半以上的比较,而且确实如此。

然而,你的比较应该是它的10倍。你的代码效率低下的原因是它一次又一次地重新开始,而不是尽可能地从它交换的地方开始。这会导致额外因素O(sqrt(N))

与此同时,对于几乎任何输入,几乎任何排序算法都比冒泡排序更好,所以即使是有效的冒泡排序也不是一种有效的排序。


我对您的代码做了一个小改动:用更惯用的单行交换替换四行交换。否则,不会更改任何内容,只需添加cmpcountswapcount变量,然后返回结果而不是打印结果。

def bogo_bubble(blist):
    cmpcount, swapcount = 0, 0
    n = 0
    while n < len(blist) - 1:
        cmpcount += 1
        if blist[n] > blist[n + 1]:
            swapcount += 1
            blist[n], blist[n+1] = blist[n+1], blist[n]
            n = 0
        else:
            n = n + 1
    return blist, cmpcount, swapcount

这是维基百科的Psuedocode implementation,翻译成Python。我不得不用repeat… unit替换while True… if not …: break,但其他一切都很简单。

def wp1_bubble(blist):
    cmpcount, swapcount = 0, 0
    while True:
        swapped = False
        for i in range(1, len(blist)):
            cmpcount += 1
            if blist[i-1] > blist[i]:
                swapcount += 1
                blist[i-1], blist[i] = blist[i], blist[i-1]
                swapped = True
        if not swapped:
            break
    return blist, cmpcount, swapcount

这是Optimizing bubble sort,它执行跳过排序尾部优化的简单版本,但不是更复杂的版本(紧随其后)。

def wp2_bubble(blist):
    cmpcount, swapcount = 0, 0
    n = len(blist)
    while True:
        swapped = False
        for i in range(1, n):
            cmpcount += 1
            if blist[i-1] > blist[i]:
                swapcount += 1
                blist[i-1], blist[i] = blist[i], blist[i-1]
                swapped = True
        n -= 1
        if not swapped:
            break
    return blist, cmpcount, swapcount

import random
alist = [random.randrange(100) for _ in range(100)]
bb, cb, sb = bogo_bubble(alist[:])
b1, c1, s1 = wp1_bubble(alist[:])
b2, c2, s2 = wp2_bubble(alist[:])
assert bb == b1 == b2
print('bogo_bubble: {} cmp, {} swap'.format(cb, sb))
print('wp1_bubble : {} cmp, {} swap'.format(c1, s1))
print('wp2_bubble : {} cmp, {} swap'.format(c2, s2))

典型输出:

bogo_bubble: 100619 cmp, 2250 swap
wp1_bubble : 8811 cmp, 2250 swap
wp2_bubble : 4895 cmp, 2250 swap

答案 1 :(得分:1)

如果我被迫使用冒泡排序,我会这样做,你应该总是在python中使用默认的sort()函数,它非常快。

def BubbleSort(A):
    end = len(A)-1
    swapped = True
    while swapped:
        swapped = False
        for i in range(0, end):
            if A[i] > A[i+1]:
                A[i], A[i+1] = A[i+1], A[i]
                swapped = True
        end -= 1

它基本上是常规的bubblesort,但不是遍历整个列表,而是每次只遍历到最后一个交换的值,根据定义,任何已经存在的值都已存在。

此外,您不需要在python中使用临时值进行交换,这样做的pythonic方法是:

a , b = b , a 

答案 2 :(得分:0)

你可以自己测试一下。其他事情保持不变,只计算迭代次数会给你一个想法,什么是更快。这是我写的:

def sort_bubble(blist):
    ops=0
    n = 0
    while n < len(blist) - 1:
        if blist[n] > blist[n + 1]:
            n1 = blist[n]
            n2 = blist[n + 1]
            blist[n] = n2
            blist[n + 1] = n1
            n = 0
        else:
            n = n + 1
        ops+=1
    print ops
    print blist

def bubbleSort(list):
    ops=0
    for i in range(len(list)):
        for j in range(i):
            if list[i] < list[j]:
                list[i], list[j] = list[j], list[i]
            ops+=1
    print ops
    return list



sort_bubble([ 6,5, 3 ,1, 8, 7, 2, 4])
print bubbleSort([ 6,5, 3 ,1, 8, 7, 2, 4])