桶排序(Bucket sort)------时间复杂度为O(n)的排序方法(一)

       之前我们分别分析了时间复杂度分别为O(n²)和O(nlogn)的排序方法,接下来,我们来分析复杂度为O(n)的排序方法,也称为线性的排序方法

       你可能会想,这几种排序方法为什么能做到线性呢?其实,这几种排序方法并不是基于比较的,也有着较为严苛的应用场景。我们先讲桶排序。

桶排序(Bucket sort)

核心思想:桶排序顾名思义,是将数据放在几个有序的桶内,将每个桶内的数据进行排序,最后有序地将每个桶中的数据从小到大依次取出,即完成了排序。

      我们举个例子来帮助理解,现在有一个数组:20,33,42,12,65,42,98,76,14,88,53,77。运用桶排序,假设我们划分5个桶,分别装0-19,20-39,40-59,60-79,80-99的数,再将每个桶中的数进行排序,可以运用快排,最后再将一个一个桶里的数依次取出,即完成排序。

下面代码实现上面这个例子的过程(重在理解桶排序的过程)

public class Main {
    @Test
    public void test() {
        int[] a = {20, 33, 42, 12, 65, 42, 98, 76, 14, 88, 53, 77};
        bucketSort(a, a.length);
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
    }

    public void bucketSort(int[] a, int n) {
        //模拟上面给的例子将a = {20, 33, 42, 12, 65, 42, 98, 76, 14, 88, 53, 77}放在5个桶里
        //新建桶集合
        List<ArrayList<Integer>> buckets = new ArrayList<>();
        //对每个桶进行初始化
        for (int i = 0; i < 5; i++) {
            buckets.add(new ArrayList<Integer>());
        }
        //将数据放在对应的桶里
        for (int i = 0; i < n; i++) {
            buckets.get(a[i]/20).add(a[i]);
        }
        for (int i = 0; i < 5; i++) {
            //模拟单个桶排序过程,这里用Collections的sort方法进行排序
            Collections.sort(buckets.get(i));
        }
        //将桶内数据依次放进数组中
        int k = 0;
        for (int i = 0; i < 5; i++) {
            for (int j = 0;; j++) {
                if(j == buckets.get(i).size()){
                    break;
                }
                a[k++] = buckets.get(i).get(j);
            }
        }
    }
}

性能分析:

       经过上面的分析,你应该懂得了桶排序的思想。不过你可能会有一个疑问:每个桶内再用其他的排序算法进行排序(比如快排),这样子时间复杂度不还是O(nlogn)吗?请看下面这段分析。  

      如果要排序的数据有n个,我们把它们分在m个桶中,这样每个桶里的数据就是k = n / m。每个桶内排序的时间复杂度就为O(k*logk)。m个桶就是m * O(k * logk)=m * O((n / m)*log(n / m))=O(nlog(n / m))。当桶的个数m接近数据个数n时,log(n/m)就是一个较小的常数,所以时间复杂度接近O(n)。


应用场景:

       看了上面的分析,既然桶排序时间复杂度为线性,是不是就能替代例如快排、归并这种时间复杂度为O(nlogn)的排序算法呢?

答案是否定的,桶排序的应用场景十分严苛,首先,数据应该分布比较均匀。讲一种较坏的情况,如果数据全部都被分到一个桶里,那么桶排序的时间复杂度是不是就退化到O(nlogn)了呢?其次,要排序的数据应该很容易分成m个桶每个桶也应该有大小顺序


这篇博文是在学习王争老师的《数据结构与算法之美》的课后总结,若有错误请指出,共同学习,谢谢~

 

 

  • 19
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
排序时间复杂度为O(nlogn),桶排序时间复杂度为O(n)。 堆排序是一种基于二叉堆的排序算法,它的时间复杂度为O(nlogn)。堆排序的过程包括建堆和排序两个步骤。建堆的时间复杂度为O(n),排序时间复杂度为O(nlogn)。因此,堆排序的总时间复杂度为O(nlogn)。 桶排序是一种线性时间复杂度排序算法,它的时间复杂度为O(n)。桶排序的过程是将待排序的元素分配到不同的桶中,然后对每个桶中的元素进行排序,最后将所有桶中的元素按顺序合并起来。由于桶排序的过程中,每个元素只需要与其他桶中的元素进行比较,所以桶排序时间复杂度为O(n)。 以下是堆排序桶排序的示例代码: 堆排序的示例代码: ```python def heapify(arr, n, i): largest = i l = 2 * i + 1 r = 2 * i + 2 if l < n and arr[i] < arr[l]: largest = l if r < n and arr[largest] < arr[r]: largest = r if largest != i: arr[i], arr[largest] = arr[largest], arr[i] heapify(arr, n, largest) def heapSort(arr): n = len(arr) for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i) for i in range(n - 1, 0, -1): arr[i], arr[0] = arr[0], arr[i] heapify(arr, i, 0) arr = [12, 11, 13, 5, 6, 7] heapSort(arr) print("Sorted array is:", arr) ``` 桶排序的示例代码: ```python def bucketSort(arr): n = len(arr) max_val = max(arr) min_val = min(arr) bucket_range = (max_val - min_val) / n buckets = [[] for _ in range(n)] for num in arr: index = int((num - min_val) / bucket_range) buckets[index].append(num) for i in range(n): buckets[i].sort() sorted_arr = [] for bucket in buckets: sorted_arr.extend(bucket) return sorted_arr arr = [12, 11, 13, 5, 6, 7] sorted_arr = bucketSort(arr) print("Sorted array is:", sorted_arr) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值