【发布时间】:2010-09-21 12:36:24
【问题描述】:
冒泡排序在现实世界中有任何用途吗?每次看到有人提到,总是这样:
- 一种可供学习的排序算法。
- 不使用的排序算法示例。
【问题讨论】:
标签: algorithm language-agnostic sorting bubble-sort
冒泡排序在现实世界中有任何用途吗?每次看到有人提到,总是这样:
【问题讨论】:
标签: algorithm language-agnostic sorting bubble-sort
冒泡排序是(可证明的)在非常特定情况下可用的最快排序。它最初之所以广为人知,主要是因为它是最早经过严格分析的算法之一(任何类型的),并且证明它在其有限的情况下是最优的。
考虑存储在磁带驱动器上的文件,以及如此小的随机存取内存(或如此大的密钥),以至于您在任何给定时间只能将 两个 记录加载到内存中。倒带速度很慢,因此在文件中进行随机访问通常是不切实际的——如果可能,您希望按顺序处理记录,一次不超过两个。
在磁带驱动器很普遍的时候,只有几千(字|字节)RAM(任何类型)的机器很常见,这足够现实,值得研究。这种情况现在很少见,因此研究冒泡排序毫无意义——但更糟糕的是,无论如何都没有教授最佳情况,所以即使/如果出现正确的情况,几乎没有人会意识到 它。
就在极小和/或几乎已排序的数据集上速度最快而言,虽然这可以掩盖冒泡排序的弱点(至少在某种程度上),但插入排序本质上总是更好/这两个。
【讨论】:
这取决于您的数据分布方式 - 是否可以做出一些假设。
我发现了解何时使用冒泡排序(或其他排序)的最佳链接之一是关于排序算法的动画视图:
【讨论】:
它在现实世界中并没有得到太多使用。这是一个很好的学习工具,因为它易于理解且实施速度很快。它具有糟糕的 (O(n^2)) 最坏情况和平均性能。当您知道数据几乎已排序时,它具有良好的最佳情况性能,但是还有许多其他算法具有此属性,具有更好的最差和平均情况性能。
【讨论】:
我最近在一个优化轶事中发现了它的一个很好的用途。一个程序需要一组按每帧深度排序的精灵。怨恨顺序在帧之间不会有太大变化,因此作为一种优化,它们是通过每帧一次通过的方式对它们进行冒泡排序的。这是在两个方向(从上到下和从下到上)完成的。所以精灵几乎总是使用非常有效的 O(N) 算法进行排序。
【讨论】:
对于 tiny 套装来说,这可能是最快的。
说到教育。 sorting out sorting最后一幕的链接,厉害了。必看。
【讨论】:
这对小型数据集很有用——这就是为什么当分区大小变小时一些 qsort 实现会切换到它。但是插入排序仍然更快,所以除了作为教学辅助之外,没有什么好的理由使用它。
【讨论】:
我们最近在算法的最优性证明中使用了冒泡排序。我们必须将由一系列对象表示的任意最优解转换为我们的算法找到的解。因为我们的算法只是“按此标准排序”,所以我们必须证明我们可以对最优解进行排序而不会使其变得更糟。在这种情况下,冒泡排序是一种非常好的算法,因为它具有很好的不变量,即只交换两个相邻且顺序错误的元素。我认为,使用更复杂的算法会使大脑融化。
您好。
【讨论】:
我认为这是一个很好的“教学”算法,因为它很容易理解和实现。出于同样的原因,它也可能对小型数据集有用(尽管一些 O(n lg n) 算法也很容易实现)。
【讨论】:
我无法抗拒对冒泡排序的任何评论,提到更快(似乎是 O(nlogn),但这并没有真正得到证明)Comb Sort。请注意,如果您使用预先计算的表,梳排序会更快一些。梳排序与冒泡排序完全相同,只是它最初不是通过交换相邻元素开始的。它几乎与冒泡排序一样容易实现/理解。
【讨论】:
Bubble sort 易于实现,并且在您拥有小型数据集时足够快。
当您的集合几乎已排序(例如,一个或多个元素不在正确的位置)时,冒泡排序足够快,在这种情况下,您最好交错从 0-index 到 n-index 以及从 n-index 到0-索引。 使用 C++ 可以通过以下方式实现:
void bubbleSort(vector<int>& v) { // sort in ascending order
bool go = true;
while (go) {
go = false;
for (int i = 0; i+1 < v.size(); ++i)
if (v[i] > v[i+1]) {
swap(v[i], v[j]);
go = true;
}
for (int i = (int)v.size()-1; i > 0; --i)
if (v[i-1] > v[i]) {
swap(v[i-1], v[i]);
go = true;
}
}
}
如果两个相邻项目的交换是筹码并且任意项目的交换很昂贵,那会很好。
由于该算法易于实现,因此易于支持,在实际应用程序生命周期中减少支持工作量很重要。
【讨论】:
我曾经在某些情况下将它用于 TRS-80 Model 1 上的小 N。 使用 for 循环,可以在一个程序行上实现完整的排序。
除此之外,它对教学很有用,有时也适用于几乎按排序顺序排列的列表。
【讨论】:
我曾经将它用于大多数情况下它将对两个项目进行排序的情况。
下次我看到该代码时,有人将其替换为库排序。我希望他们首先对其进行基准测试!
【讨论】:
(a < b)? (swap):(do-not-swap)?
编写代码既快速又简单(几乎不可能出错)。如果您不做繁重的工作并且没有图书馆分类支持,它就有它的位置。
【讨论】:
实际上这是我最常使用的那种。 (在我们的项目中,我们不能使用任何外部库。)
当我确定数据集非常小时它很有用,所以我一点也不关心速度,想要最短和最简单的代码。
泡沫不是最低的。最近,我遇到了需要对三个元素进行准确排序的情况。我写了这样的东西:
// Use sort of stooge to sort the three elements by cpFirst
SwapElementsIfNeeded(&elementTop, &elementBottom);
SwapElementsIfNeeded(&elementTop, &elementMiddle);
SwapElementsIfNeeded(&elementMiddle, &elementBottom);
*pelement1 = elementTop;
*pelement2 = elementMiddle;
*pelement3 = elementBottom;
【讨论】:
哦,是的,这是一个很好的选择机制。如果您在某人编写的代码中找到它,您就不会雇用他。
【讨论】:
大部分什么都没有。请改用 QuickSort 或 SelectionSort...!
【讨论】: