桶排序算法(含Python/Java/C/C++程序)

2025年7月15日 | 阅读13分钟

桶排序是一种排序算法,它将元素分成多个组,称为桶。桶排序中的元素首先被均匀地分成称为桶的组,然后使用任何其他排序算法进行排序。之后,按排序方式收集元素。

算法

桶排序的步骤

步骤1:创建s个大小的空列表(或桶),其中s是数组的大小。

步骤2:将inputArr[j]插入到bucket[s * inputArr[j]]中

步骤3:使用插入排序对各个桶进行排序。

步骤4:按顺序从桶中收集已排序的元素,并将它们存储在输入数组中。

步骤5:打印已排序的列表。

桶排序算法的工作原理

我们将使用散布-收集方法来理解桶排序算法。在此方法中,给定的元素首先被分发到桶中。分发工作完成后,每个桶中的元素使用插入排序算法进行排序。最后,按顺序收集已排序的元素。

让我们采用一个未排序的数组来理解桶排序的过程。通过示例理解桶排序会更容易。

我们将输入数组设为

Bucket Sort Algorithm (With Program in Python/Java/C/C++)

现在,我们创建一个大小为10的数组,其中每个元素都充当一个桶。

Bucket Sort Algorithm (With Program in Python/Java/C/C++)

现在,我们需要根据范围将元素分类到桶中。例如,如果我们想插入元素0.77,那么我们将0.77乘以10,即0.77 × 10 = 7.7。现在,取7.7的整数部分,即7。因此,0.77落在索引为7的桶中。同样,我们可以放置输入数组中的其他元素。添加所有数组元素后,桶将如下所示。

Bucket Sort Algorithm (With Program in Python/Java/C/C++)

现在,我们对每个桶应用插入排序。之后,桶将如下所示。

Bucket Sort Algorithm (With Program in Python/Java/C/C++)

最后,我们按顺序从桶中收集已排序的元素,并将它们存储在输入数组中。现在,输入数组将如下所示。

Bucket Sort Algorithm (With Program in Python/Java/C/C++)

我们可以看到数组已完全排序。

Python/Java/C/C++/C# 中桶排序的实现

Python 程序

立即执行

Java 程序

编译并运行

C++ 程序

编译并运行

C 语言程序

编译并运行

C# 程序

编译并运行

输出

Array before sorting is:
0.77 0.16 0.38 0.25 0.71 0.93 0.22 0.11 0.24 0.67
Array after sorting is:
0.11 0.16 0.22 0.24 0.25 0.38 0.67 0.71 0.77 0.93

复杂度分析

现在,让我们看看桶排序在最佳情况、平均情况和最坏情况下的时间复杂度。我们还将查看桶排序的空间复杂度。

时间复杂度

最佳情况复杂度:最佳情况发生在不需要排序时,即输入数组已排序。在桶排序中,当元素在桶中均匀分布时,会出现最佳情况。当元素已经在桶中排序时,复杂度会更好。

假设有人使用插入排序来对桶元素进行排序。在这种情况下,总时间复杂度将是线性的,即 O(n + k),其中 O(n) 用于创建桶,O(k) 用于使用在最佳情况下具有线性时间复杂度的算法对桶元素进行排序。桶排序的最佳情况时间复杂度为O(n + k)

平均情况复杂度:平均情况发生在数组元素杂乱无章时,即既不完全降序也不完全升序。桶排序的平均情况时间复杂度为O(n + K)

最坏情况复杂度:当一个桶接收输入数组的所有元素时,就会发生最坏情况。在这种情况下,插入排序将在数组的所有元素上运行。因此,时间复杂度为O(n2)。请注意,如果使用合并排序或堆排序对各个桶进行排序,则可以降低这种情况下的时间复杂度。

情况时间复杂度
最佳情况O(n + k)
平均情况O(n + k)
最坏情况O(n2)

空间复杂度

桶排序的空间复杂度为O(n + k),其中'n'是要排序的输入数组中的元素总数,'k'是桶的总数。这是因为还需要额外的空间来存储桶本身(O(k)),以及将数组元素保存在这些桶内(最坏情况下为 O(n),如果每个元素都落入特定桶中)。因此,总体空间复杂度是这两者的总和。

空间复杂度O(n + k)
稳定版取决于使用的排序算法

桶排序可能是一个稳定的排序算法,也可能不是。因为我们使用插入排序来对存储在桶中的元素进行排序,而插入排序是一种稳定的算法。因此,在本教程中,我们可以说桶排序是一种稳定的算法。如果我们使用一种不稳定的排序算法,那么桶排序也将不稳定。

桶排序的优点

对均匀分布的数据高效:当输入数据在范围内均匀分布时,桶排序效果很好。在这种情况下,桶排序可以实现接近线性的时间复杂度,使其比快速排序合并排序等其他比较排序更快。

线性时间复杂度(最佳情况):当数据分布良好时,桶排序可以实现 O(n + k) 的最佳情况时间复杂度,其中 n 是元素数量,k 是桶的数量。这使得桶排序对于特定类型的数据集非常快速。

提供并行化:如果我们观察桶排序的排序性质,我们会发现每个桶都可以独立排序,这有利于并行处理。因此,它可以在拥有多个处理器或内核的系统中提高性能。

易于实现和简单:与快速排序等更复杂的算法相比,桶排序的实现和理解相对简单。这可能是一个巨大的优势,尤其是在开发时间有限的情况下。

可应用于不同的排序算法:为了对桶内的数组元素进行排序,桶排序可以与其他排序算法结合使用,如插入排序或合并排序。因此,桶排序在选择适合特定数据类型的排序方法方面提供了灵活性。

桶排序的缺点

不适合非均匀数据:我们已经看到,如果输入数据分布不均匀,桶排序效果不佳。在这种情况下,一些桶将拥有更多元素,而其他桶可能保持为空。这可能导致工作负载分布不均,进而导致性能下降,使其可能比其他排序算法慢。在最坏的情况下(当所有输入元素都进入特定桶时),桶排序时间复杂度会上升到 O(n2) 时间复杂度。

需要额外空间:在此排序算法中,选择合适的桶数非常重要。过少的桶可能导致元素分布不均和桶内排序缓慢,而过多的桶可能导致空间浪费。

选择桶的排序算法:用于对每个桶内的元素进行排序的算法会影响整体性能。如果为桶排序选择的算法效率较低,则会阻碍整个排序过程。此外,决定选择合适的桶数需要对数据分布有所了解,这在事先确定时可能很麻烦。

仅限于特定数据类型:桶排序对于数值数据类型,特别是浮点数更为有效。桶排序不适用于所有数据类型。

桶创建和管理开销:桶的创建和管理会带来开销,尤其是对于具有大量元素或广泛值范围的数据集。

结论

桶排序主要用于以下两种情况之一。第一种是提高排序过程的速度。将元素放入桶中然后应用排序算法的过程比气泡排序等线性算法快得多。但是,代价是桶排序比线性算法消耗更多的内存。

桶排序选择题

1) 桶排序最有效的情况是 __________。

  1. 输入分布不均匀。
  2. 输入分布均匀。
  3. 输入分布随机。
  4. 输入范围很大。
 

答案: b)

解释:当输入数据在范围内均匀分布时,桶排序效果很好。在这种情况下,桶排序可以实现接近线性的时间复杂度。


2) 桶排序的最坏情况时间复杂度是多少(k 是桶的数量)?

  1. O(n + k)
  2. O(n * k2)
  3. O(n2)
  4. O(n * log(n))
 

答案:c)

解释:当一个桶接收输入数组的所有元素时,就会发生最坏情况。在这种情况下,插入排序将在数组的所有元素上运行。因此,时间复杂度为 O(n2)。这里,请注意,桶的数量没有起任何重要作用,因为一个桶接收了所有元素。


3) 下列哪一项不会影响桶排序的时间复杂度?

  1. 用于对各个桶进行排序的算法实现
  2. 使用的桶数
  3. 输入分布
  4. 输入值
 

答案: d)

解释:各种因素都会影响桶排序的时间复杂度。这些因素包括用于对各个桶进行排序的算法的实现、使用的桶数以及桶中输入值的分布。它不依赖于输入值。


4) 下列哪一个不一定是一个稳定的排序算法?

  1. 合并排序
  2. 桶排序
  3. 计数排序
 

答案: b)

解释:合并排序计数排序是稳定的排序算法。然而,桶排序不能保证如此。桶排序的稳定性主要取决于用于对桶中的元素进行排序的排序算法。如果使用的排序算法是稳定的,那么桶排序就是稳定的;否则不是。


5) 下列哪种排序不使用比较排序算法?

  1. 冒泡排序
  2. 插入排序
  3. 选择排序
  4. 桶排序
 

答案: d)

解释:气泡排序、插入排序和选择排序使用比较排序进行排序。桶排序利用元素在桶中的分布来完成排序工作。