【问题标题】:Under what circumstances is bidirectional bubble sort better than standard bubble sort?在什么情况下双向冒泡排序优于标准冒泡排序?
【发布时间】:2017-07-18 18:24:35
【问题描述】:

我已经实现了双向冒泡排序算法。但我想不出双向冒泡排序比标准冒泡排序更好的场景……有人能给我一些线索吗?

我在 Python 中的实现:

def bubbleSort_v(my_list):
    s = 0
    e = 0
    right = True
    for index in range(len(my_list)-1,0,-1):
        if right:
            right = False
            for idx in range(s,index+e,1):
                if my_list[idx] > my_list[idx+1]:
                    my_list[idx],my_list[idx+1] = my_list[idx+1],my_list[idx]
            s += 1
        else:
            right = True
            for idx in range(index-1+s,e,-1):
                if my_list[idx] < my_list[idx-1]:
                    my_list[idx],my_list[idx-1] = my_list[idx-1],my_list[idx]
            e += 1
    return my_list

谢谢!

【问题讨论】:

  • 在所有情况下都很糟糕
  • 维基百科上的介绍和“与冒泡排序的区别”都通过示例讨论了您的问题。 en.wikipedia.org/wiki/Cocktail_shaker_sort
  • 朋友不要让朋友使用冒泡排序。研究冒泡排序家族的唯一原因是因为它们易于理解,而且通常很容易解释为什么几乎所有其他排序算法都更胜一筹(当然,不包括像 bogosort 这样疯狂的东西)。
  • @GarrGodfrey 不是全部。如果您的数据已经排序或接近排序,则可以接受冒泡排序。也许仍然不是最好的选择,但至少不是糟糕。
  • Mark Ransom 所说的。 OTOH,Python 出色的 TimSort 也非常擅长对包含已排序序列的数据进行排序。因此,如果您有一个排序列表并将随机内容附加(或插入)到它并重新排序,TimSort 将有效地处理这项工作。同样,它将有效地合并来自已连接在一起的一堆排序列表的数据。

标签: python algorithm bubble-sort


【解决方案1】:

如果有一个元素位于列表的右侧(例如最后一个索引),则应将其移动到列表的左侧(例如第一个索引)。单向冒泡排序需要很长时间:每次它只会移动一步。

如果我们执行双向冒泡排序,则元素将在第一步向右移动。

因此,一般情况下,一个或多个元素应该移动(在很多地方)在完成单向冒泡排序的相反方向上会更好。强>

对于冒泡排序的实现,它不会产生太大影响:通常冒泡排序会在排序时进行测试。如果它可以在没有交换的情况下完全运行,它就会停止工作。

例如移动到右侧的单向冒泡排序:

def single_bubble(data):
    for i in range(len(data)):
        can_exit = True
        for j in range(len(data)-i-1):
            if data[j] > data[j+1]:
                data[j],data[j+1] = data[j+1],data[j]
                can_exit = False
        if can_exit:
            return

因此,如果您想将一个元素向 left 移动大量位置,那么对于每个这样的步骤,您都必须再次执行完整的循环。我们可以对上面的方法再优化一点,但是这种行为是无法消除的。

双向冒泡排序可以这样实现:

def single_bubble(data):
    for i in range(len(data)):
        can_exit = True
        for j in range(len(data)-i-1):
            if data[j] > data[j+1]:
                data[j],data[j+1] = data[j+1],data[j]
                can_exit = False
        if can_exit:
            return
        for j in range(len(data)-i,i,-1):
            if data[j-i] > data[j]:
                data[j-1],data[j] = data[j],data[j-1]
                can_exit = False
        if can_exit:
            return

话虽如此,冒泡排序不是一般来说是一个好的排序算法。存在更好的算法,例如 quicksort、mergesort、timsort、radixsort(用于数值数据)等。

即使在 O(n2) 算法中,冒泡排序实际上也是一个相当糟糕的算法,因为它一次将对象移动一个位置。插入排序将简单地首先计算必须移动的内容,然后快速移动列表的那部分,从而节省大量无用的移动。但是,在学习设计、实现和分析算法时,这些算法可以起到教育目的,因为与更高级的算法相比,这些算法的性能会差很多。

自己实现(通用)排序功能可能没有好处:已经为所有流行的编程语言实现了良好的算法,并且这些算法速度快、消耗内存少等。

【讨论】:

  • 嗯,对于大列表,O(n log n) 排序,如快速排序或合并排序会更好,但对于较小的列表,O(n^2) 可能更快,这就是为什么我们有混合算法,对小(子)列表使用 O(n^2)。但即使在 O(n^2) 排序中,冒泡排序也比(例如)选择排序或插入排序更糟糕。
  • @PM2Ring:是的,但对于小型列表,性能通常不是问题。我认为无论算法如何,对包含 10 个元素的列表进行排序都不会显着提高程序的性能。通常在这种情况下,瓶颈在其他地方。时间复杂度仅与大量数据有关。
  • 当然,在 Python 中你几乎应该总是使用 TimSort,除非你知道像 radixsort 这样的东西适合你的数据。 OTOH,尽管所有现代语言都提供了排序工具,但对于 compsci 学生来说学习各种标准排序算法仍然是一个好主意,不是因为他们需要在现实世界中实现它们,而是因为它们是一个很好的主题了解算法分析。
猜你喜欢
  • 1970-01-01
  • 2013-03-27
  • 2015-09-12
  • 2014-02-04
  • 2022-01-09
  • 2017-03-23
  • 2015-09-16
  • 2013-04-18
相关资源
最近更新 更多