热门课程

免费试听

上课方式

开班时间

当前位置: 首页 -   文章 -   新闻动态 -   正文

Java经典算法——桶排序

知了堂姐
2024-07-09 11:12:24
0

1、什么是桶排序?

桶排序是一种稳定的排序算法。它的工作原理是将序列中的元素分布到一定数量的桶内,然后分别对每个桶内的元素进行排序,最后再将各个桶内的有序子序列放回原始序列中。对于单个桶内的元素排序,我们可以使用别的排序算法,也可以递归使用桶排序。一般来说,对于单个桶内的元素,使用插入排序算法对它们进行排序。

2、问题

假设目前有包含 100,200,300,400,500,600 共 6 个数字的一个随机顺序的集合。我们需要对这个集合进行桶排序。

3、分析桶排序

桶排序需要思考两个问题,有多少个桶?每个桶多大也就是每个桶放多少?

首先我们设置桶的大小为 2 。

然后一共有6个数字,除以每个桶的大小,就是需要多少个桶,在这里我们需要3个桶。

现在有桶了,我们需要一个方法找到元素对应的桶。我们使用一个计算公式来计算所属哪个桶:f(x) = (int)((x - min) / (max - min + 1.0) * 桶个数)。

(x - min) / (max - min + 1.0) 计算出的结果 是一个大于等于0,最大趋近于1且不等于1的值,然后乘以桶的个数进行强转整数类型,就可以计算出0-9之间的一个数字,就代表具体的桶编号。之所以用这个公式,是因为这个公式会随着 x 的变大而变大,可以保证桶内数据是在某个范围内,且后边的桶比前边的桶内存放的数据要大。

每个桶都存放完成后,遍历10个桶,每个桶都进行插入排序。排序完一个桶后就将这个桶中的数据放回原先的集合中。

4、步骤

  1. 设置几个数组作为空桶。
  2. 从左到右遍历待排序序列,把每个元素都放到对应的桶中
  3. 对每个不是空的桶进行排序
  4. 依次取出所有桶中的元素放回原序列

5、根据《算法》中描述每个桶的大小在 5~10 之间性能最优。

时间空间复杂度分析:

空间复杂度:因为排序过程中用到了一个辅助桶来存储元素,所以空间复杂度是O(n)

时间复杂度:有 n 个待排序元素,均匀地将这些元素划分到 bucketCount 个桶内,每个桶里就有 k=n/bucketCount 个元素。每个桶内部使用快速排序,时间复杂度为 O(k logk)。m 个桶排序的时间复杂度就是 O(bucketCount k logk),因为 k=n/bucketCount,所以整个桶排序的时间复杂度就是 O(nlog(n/bucketCount))。当桶的个数 bucketCount 接近数据个数 n 时,log(n/bucketCount) 就是一个非常小的常量,这个时候桶排序的时间复杂度接近 O(n)。所以时间复杂度为O(n)

桶排序的适应场景

桶排序对数据要求较高,适用于数据是均匀分布的情况,这样可以让分布到各个桶内的元素数量相当。而不是被集中分配到其中一个桶或几个桶。

比较适合用在外部排序中。

因为数据量比较大,数据存储在外部磁盘中,无法一次性全部放入内存进行排序,一部分一部分的读入内存再写入磁盘,这种方式称为外部排序。

代码实现

Java实现代码

public class BucketSort {
    private void insertionSort(List arr) {
      if (arr == null || arr.size() == 0) return;
      for (int i = 1; i < arr.size(); ++i) {
        int cur = arr.get(i);
        int j = i - 1;
        while (j >= 0 && arr.get(j) > cur) {
          arr.set(j+1, arr.get(j));
          --j;
        }
        arr.set(j+1, cur);
      }
    }
    private int bucketSize;
    public BucketSort(int bucketSize) {
      this.bucketSize = bucketSize;
    }
    public void sort(int[] arr) {
      if (arr == null || arr.length == 0) return;
      int max = arr[0], min = arr[0];
      for (int num: arr) {
        if (num > max) max = num;
        if (num < min) min = num;
      }
      int bucketCount = arr.length / bucketSize;
      List> buckets = new ArrayList<>(bucketCount);
      for (int i = 0; i < bucketCount; ++i)
        buckets.add(new ArrayList<>());
      for (int num: arr) {
        int idx = (int)((num - min) / (max - min + 1.0) * bucketCount);
        buckets.get(idx).add(num);
      }
      int idx = 0;
      for (List bucket: buckets) {
        insertionSort(bucket);
        for (int num: bucket)
          arr[idx++] = num;
      }
    }
 }

JavaScript实现代码

def Bucket_Sort(array, bucketsize):
    minValue = min(array)
    maxValue = max(array)
    res = []
    bucketcount = (maxValue - minValue + 1) // bucketsize
    bucket_lists = [[] for i in range(bucketcount)]
    
    for i in array:
        bucket_index = (i - minValue) // bucketsize
        bucket_lists[bucket_index].append(i)
    # 桶内排序
    for j in bucket_lists:
        Quick_Sort_2(j, 0, len(j)-1)    

    for j in bucket_lists:
        if len(j) != 0:
            res.extend(j)
    return res

进阶之路

查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。所以在面试中经常会问到排序算法及其相关的问题。但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。

一般在面试中最常考的是快速排序归并排序,并且经常有面试官要求现场写出这两种排序的代码。对这两种排序的代码一定要信手拈来才行。还有插入排序、冒泡排序、堆排序、基数排序、桶排序等。

面试官对于这些排序可能会要求比较各自的优劣、各种算法的思想及其使用场景。还有要会分析算法的时间和空间复杂度。通常查找和排序算法的考察是面试的开始,如果这些问题回答不好,估计面试官都没有继续面试下去的兴趣了。

所以想开个好头,就要把常见的排序算法思想及其特点熟练掌握,有必要时能熟练写出代码。


 

大家都在看

企业项目经理走进课堂与学员交流学习

2024-07-09 浏览次数:0

ui设计适合女生吗?哪家培训班好?

2024-07-09 浏览次数:0

当下适合入行的IT职业有哪些?

2024-07-09 浏览次数:0

Ui设计师需要掌握什么样的知识架构呢?Ui设计师...

2024-07-09 浏览次数:0

Vim编辑器五大模式介绍

2024-07-09 浏览次数:0

双旦节来啦!惊喜好礼送不停~~

2024-07-09 浏览次数:0
最新资讯
成都java程序员培训可靠吗?...   成都java程序员培训可靠吗?这个问题是我们找培训机构最看重的,毕竟培训费用也是不便宜的,如果花...
java和web前端哪个好找工...   java和web前端哪个好找工作?很多人都很迷茫,因为看就业情况,Java和前端都是IT行业的热...
成都Java培训课程哪家好?要...   5月23日,是Java27岁的生日,Java作为一门热门的编程语言,一直以来是很多人转行首选语言...
Java培训学什么?只学习Ja...   Java培训学什么?很多想报名Java培训的人都比加关注这个问题,毕竟学费并不低,如果只单单学习...
java培训哪里好?靠谱Jav...   Java培训哪里好?想要找到一个好的、靠谱的Java培训机构,那么一定要记住这些靠谱Java培训...
java培训班学费一般多少?   java培训班学费一般多少?俗话说钱不是万能的,但是没有钱是万万不能的,我们想去参加Java培训...
Java 学习前景如何?探索未...   学Java还有前景吗?这个得看看市场需求:  根据2020年TIOBE开发语言排行榜宣布的流行开...
当兵两年,回来继续学Java   当兵两年,回来继续学Java  人这一生就像一部半开放式结局的电影,有大致的时间线,却没有准备好...