5-1 其他排序:桶排序

桶排序

桶排序是一种排序技术,它将元素分成若干组(或称桶)。这些桶是通过均匀分布元素而形成的。元素被划分到不同的桶中后,就可以使用任何其他排序算法对它们进行排序。最后,将排序后的元素按顺序重新组合在一起。

  • 当输入数组元素均匀分布在一个范围内时,该方法效果很好。
  • 这是一个稳定的算法,因为我们使用插入排序(它本身就是稳定的)来对各个桶进行排序。

桶排序算法
创建n 个空桶(或列表),并对数组中的每个元素 arr[i] 执行以下操作。

  • 将 arr[i] 插入 bucket[n*array[i]]
  • 使用插入排序对各个桶进行排序。
  • 将所有已排序的桶连接起来。

逐步图解
要对输入数组[0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.68]应用桶排序,我们遵循以下步骤:

步骤 1:创建一个大小为 10 的数组,其中每个槽位代表一个桶。

image

步骤 2:根据元素的范围,将输入数组中的元素插入到桶中。
将元素插入桶中:

  • 将每个元素乘以桶数组的大小(本例中为 10)。例如,对于元素 0.23,我们得到 0.23 * 10 = 2.3。
  • 将结果转换为整数,即可得到桶索引。在本例中,2.3 被转换为整数 2。
  • 将元素插入到与计算出的索引对应的桶中。
  • 对输入数组中的所有元素重复这些步骤。

image

步骤 3:对每个桶中的元素进行分类。
对每个桶中的元素进行排序:

  • 应用稳定的排序算法(例如插入排序)对每个桶中的元素进行排序。
  • 每个桶中的元素现在都已排序。

image

步骤 4:将每个桶中的元素收集起来,并将它们放回原来的数组中。
从每个桶中收集元素:

  • 按顺序遍历每个桶。
  • 将桶中的每个元素分别插入到原始数组中。

image

步骤 5:原始数组现在包含已排序的元素。
使用桶排序对给定的输入进行排序后的最终数组为 [0.12, 0.17, 0.21, 0.23, 0.26, 0.39, 0.68, 0.72, 0.78, 0.94]。

image

代码实现

#include <iostream>
#include <vector>

// Insertion sort function to sort individual buckets
void insertionSort(std::vector<float>& bucket)
{
    for (int i = 1; i < bucket.size(); ++i)
    {
        float key = bucket[i];
        int j = i - 1;
        while (j >= 0 && bucket[j] > key)
        {
            bucket[j + 1] = bucket[j];
            j--;
        }
        bucket[j + 1] = key;
    }
}

// Function to sort arr[] of size n using bucket sort
void bucketSort(float arr[], int n)
{
    // 1) Create n empty buckets
    std::vector<float> b[n];

    // 2) Put array elements in different buckets
    for (int i = 0; i < n; i++)
    {
        int bi = n * arr[i];
        b[bi].push_back(arr[i]);
    }

    // 3) Sort individual buckets using insertion sort
    for (int i = 0; i < n; i++)
    {
        insertionSort(b[i]);
    }

    // 4) Concatenate all buckets into arr[]
    int index = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < b[i].size(); j++)
        {
            arr[index++] = b[i][j];
        }
    }
}

// Driver program to test above function
int main()
{
    float arr[] = {0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434};
    int n = sizeof(arr) / sizeof(arr[0]);
    bucketSort(arr, n);

    std::cout << "Sorted array is \n";
    for (int i = 0; i < n; i++)
    {
        std::cout << arr[i] << " ";
    }
    return 0;
}

输出:
image


桶排序算法的复杂度分析:

时间复杂度:

  • 最坏情况时间复杂度: O(n² )。最坏情况是指一个桶包含所有元素。在这种情况下,我们需要对所有元素执行插入排序,因此时间复杂度为 O(n² )。我们可以通过使用 O(n log n) 的算法(例如归并排序或堆排序)对各个桶进行排序,将最坏情况时间复杂度降低到 O(n log n)。但是,这种方法仅适用于桶中元素数量较少的情况,因为插入排序更适合处理小数组。
  • 最佳情况时间复杂度: O(n + k) 最佳情况是每个桶中的元素数量相等。在这种情况下,每次调用插入排序的时间复杂度均为常数,因为每个桶中的元素数量都是恒定的(假设 k 与 n 成线性比例关系)。

辅助空间: O(n+k)

posted @ 2026-03-30 18:11  游翔  阅读(0)  评论(0)    收藏  举报