算法桶排序(Bucket Sort)详解

Posted Kant101

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法桶排序(Bucket Sort)详解相关的知识,希望对你有一定的参考价值。

1. 概述

桶排序(Bucket Sort)又称箱排序,是一种比较常用的排序算法。其算法原理是将数组分到有限数量的桶里,再对每个桶分别排好序(可以是递归使用桶排序,也可以是使用其他排序算法将每个桶分别排好序),最后一次将每个桶中排好序的数输出。

2. 算法详解


3. 测试

JAVA

import java.util.ArrayList;

/**
 * @author yumu
 * @date 2022/8/25
 */
public class BucketSort 

    public void bucketSort(int[] nums) 
        int n = nums.length;
        int mn = nums[0], mx = nums[0];
        // 找出数组中的最大最小值
        for (int i = 1; i < n; i++) 
            mn = Math.min(mn, nums[i]);
            mx = Math.max(mx, nums[i]);
        
        int size = (mx - mn) / n + 1; // 每个桶存储数的范围大小,使得数尽量均匀地分布在各个桶中,保证最少存储一个
        int cnt = (mx - mn) / size + 1; // 桶的个数,保证桶的个数至少为1
        ArrayList<Integer> buckets[] = new ArrayList[cnt]; // 声明cnt个桶
        for (int i = 0; i < cnt; i++) 
            buckets[i] = new ArrayList<>();
        
        // 扫描一遍数组,将数放进桶里
        for (int i = 0; i < n; i++) 
            int idx = (nums[i] - mn) / size;
            buckets[idx].add(nums[i]);
        
        // 对各个桶中的数进行排序,这里用库函数快速排序
        for (int i = 0; i < cnt; i++) 
            buckets[i].sort(null); // 默认是按从小到大排序
        
        // 依次将各个桶中的数据放入返回数组中
        int index = 0;
        for (int i = 0; i < cnt; i++) 
            for (int j = 0; j < buckets[i].size(); j++) 
                nums[index++] = buckets[i].get(j);
            
        
    

    public static void main(String[] args) 
        int[] nums = 19, 27, 35, 43, 31, 22, 54, 66, 78;
        BucketSort bucketSort = new BucketSort();
        bucketSort.bucketSort(nums);
        for (int num: nums) 
            System.out.print(num + " ");
        
        System.out.println();
    


C++

#include <iostream>
#include <vector>

using namespace std;

class BucketSort 
public:
    void bucketSort(vector<int> &nums) 
        int n = nums.size();
        int mn = nums[0], mx = nums[0];
        for (int i = 1; i < n; i++) 
            mn = min(mn, nums[i]);
            mx = max(mx, nums[i]);
        
        int size = (mx - mn) / n + 1;   // size 至少要为1
        int cnt = (mx - mn) / size + 1; // 桶的个数至少要为1
        vector<vector<int>> buckets(cnt);
        for (int i = 0; i < n; i++) 
            int idx = (nums[i] - mn) / size;
            buckets[idx].push_back(nums[i]);
        
        for (int i = 0; i < cnt; i++) 
            sort(buckets[i].begin(), buckets[i].end());
        
        int index = 0;
        for (int i = 0; i < cnt; i++) 
            for (int j = 0; j < buckets[i].size(); j++) 
                nums[index++] = buckets[i][j];
            
        
    
;


int main() 
    vector<int> nums = 19, 27, 35, 43, 31, 22, 54, 66, 78;
    BucketSort().bucketSort(nums);
    for (auto num: nums) 
        cout << num << " ";
    
    cout << endl;
    return 0;


4. 时间复杂度和空间复杂度分析

最好时间复杂度 : O(n + k)
其中k为桶的个数。即当数据是均匀分散排列的,那么每个桶分到的数据个数都是一样的,这个步骤需要O(k)的书剑复杂度,在对每个桶进行排序的时候,最好情况下是数据都已经是有序的了,那么最好的排序算法的时间复杂度会是O(n),因此总的时间复杂度是 O(n + k)

最坏时间复杂度O(n^2)
当对每个桶中的数据进行排序的时候,所使用的排序算法,最坏情况下是O(n^2),因此总的最坏情况下的时间复杂度为O(n^2)。

平均时间复杂度O(n + n²/k + k) <=> O(n)
如果k是根据Θ(n)来获取的,那么平均时间复杂度就是 O(n)。


5. 参考文献

[1] https://iq.opengenus.org/time-and-space-complexity-of-bucket-sort/
[2] https://www.programiz.com/dsa/bucket-sort

以上是关于算法桶排序(Bucket Sort)详解的主要内容,如果未能解决你的问题,请参考以下文章

排序算法:Bucket Sort 桶排序

排序桶排序 bucket sort

bucket sort 桶排序

经典算法之桶排序

桶排序 bucket sort

桶排序(Bucket Sort)