桶排序

桶排序(Bucket Sort)顾名思义,会用到“桶”,我们可以将其想象成一个容器,核心思想是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了,换句话说:桶排序是将待排序集合中处于同一个值域的元素存入同一个桶中,也就是根据元素值特性将集合拆分为多个区域,则拆分后形成的多个桶,从值域上看是处于有序状态的。对每个桶中元素进行排序,则所有桶中元素构成的集合是已排序的。

桶排序过程中存在两个关键环节

  1. 元素值域的划分,也就是元素到桶的映射规则。映射规则需要根据待排序集合的元素分布特性进行选择,若规则设计的过于模糊、宽泛,则可能导致待排序集合中所有元素全部映射到一个桶上,若映射规则设计的过于具体、严苛,则可能导致待排序集合中每一个元素值映射到一个桶上。
  2. 从待排序集合中元素映射到各个桶上的过程,并不存在元素的比较和交换操作,在对各个桶中元素进行排序时,可以自主选择合适的排序算法,每个桶内的排序算法的复杂度和稳定性,决定了最终的算法的复杂度和稳定性。

桶排序比较适合用在非内存排序中。

所谓的非内存排序就是说数据存储在外部磁盘中,数据量比较大,内存有限,无法将数据全部加载到内存中。此外由桶排序的过程可知,当待排序集合中存在元素值相差较大时,对映射规则的选择是一个挑战,有时可能导致元素集中分布在某一个桶中或者绝大多数桶是空桶的现象,对算法的时间复杂度或空间复杂度有较大的影响,所以桶排序适用于元素值分布较为集中的序列,或者说待排序的元素能够均匀分布在某一个范围[MIN, MAX]之间。

桶排序算法具体的描述:

  • 人为设置一个 BucketSize,作为每个桶所能放置多少个不同数值(例如当BucketSize==5时,该桶可 以存放{1,2,3,4,5}这几种数字,但是容量不限,即可以存放 100 个 3);
  • 遍历输入数据,并且把数据一个一个放到对应的桶里去;
  • 对每个不是空的桶进行排序,可以使用其它排序方法,也可以递归使用桶排序;
  • 从不是空的桶里把排好序的数据拼接起来。

注意如果递归使用桶排序为各个桶排序,则当桶数量为 1 时要手动减小BucketSize 增加下一循环桶的数量,否则会陷入死循环,导致内存溢出。

代码实现

public class BucketSort {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(5);list.add(2);list.add(2);list.add(6);list.add(9);list.add(0);list.add(3);list.add(4);List<Integer> bucketSort = bucketSort(list, 2);System.out.println(bucketSort);}public static List<Integer> bucketSort(List<Integer> array,int bucketSize) {//合法性校验if (array == null || array.size() < 2 || bucketSize < 1) {return array;}//找出集合中元素的最大值和最小值int max = array.get(0);int min = array.get(0);for (int i = 0; i < array.size(); i++) {if (array.get(i) > max) {max = array.get(i);}if (array.get(i) < min) {min = array.get(i);}}//计算桶的个数   集合中的最小值到最大值 判断桶的个数int bucketCount = (max - min) / bucketSize + 1;//按照顺序创建桶 创建一个list带下标List<List<Integer>> bucketList = new ArrayList<>();for (int i = 0; i < bucketCount; i++) {bucketList.add(new ArrayList<Integer>());}//将待排序的集合依次添加到对应的桶中//首先找到元素所对应的桶的顺序  再将元素添加到桶中for (int j = 0; j < array.size(); j++) {int bucketIndex = (array.get(j) - min) / bucketSize;bucketList.get(bucketIndex).add(array.get(j));}//将桶内的元素进行排序List<Integer> resultList = new ArrayList<>();for (int j = 0; j < bucketList.size(); j++) {List<Integer> everyBucket = bucketList.get(j);if (everyBucket.size() >0) {if (bucketCount == 1) {bucketSize--;}//递归调用  进行排序List<Integer> temp = bucketSort(everyBucket,bucketSize);for (int i = 0; i < temp.size(); i++) {//合并数据resultList.add(temp.get(i));}}}return resultList;}
}

1:桶排序的时间复杂度是多少?

桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,如果我们将待排序元素映射到某一个桶的映射规则做的很好的话,很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。我们一般对每个桶内的元素进行排序时采用快排也可以采用递归桶排序,通过我们刚开始的分析,当我们对每个桶采用快排时如果桶的个数接近数据规模 n 时,复杂度为 O(n),如果在极端情况下复杂度退化为 O(n* log n)。

2:桶排序的空间复杂度是多少?

由于需要申请额外的空间来保存元素,并申请额外的空间来存储每个桶,所以空间复杂度为 O(N+M),其中 M 代表桶的个数。所以桶排序虽然快,但它是采用了用空间换时间的做法。

3:桶排序是稳定的排序算法吗?

桶排序是否稳定取决于对每一个桶内元素排序的算法的稳定性,如果我们对桶内元素使用快排时桶排序就是一个不稳定的排序算法。

排序算法----桶排序(java版)相关推荐

  1. 十大经典排序算法-桶排序算法详解

    十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...

  2. 排序算法---冒泡排序(java版)

    冒泡排序 原理 冒泡排序(Bubble Sort)是一种简单的排序算法,它通过依次比较两个相邻的的元素,看两个元素是否满足大小关系要求,如果不满足则交换两个元素.每一次冒泡会让至少一个元素移动到它应该 ...

  3. 排序算法---插入排序(java版)

    直接插入排序 原理 直接插入排序(Insertion Sort)的原理是:将数组中的数据分为两个区间,已排序区间和未排序区间.初始已排序区间只有一个元素,就是数组的第一个元素.插入算法的核心思想是取未 ...

  4. 排序算法---快速排序(java版)

    快速排序 原理 快速排序(Quick Sort)算法,简称快排,利用的也是分治的思想,快排的思路是:如果要对 m->n 之间的数列进行排序,我们选择 m->n 之间的任意一个元素数据作为分 ...

  5. 疯子的算法总结(六) 复杂排序算法 ② 桶排序

    从<基于比较的排序结构总结 >中我们知道:全依赖"比较"操作的排序算法时间复杂度的一个下界O(N*logN).但确实存在更快的算法.这些算法并不是不用"比较& ...

  6. 排序算法----桶排序(数组)

    桶排序是一种效率很高的排序算法,它的时间复杂度为O(N+M),(N个元素,范围为0--M),但桶排序有一定的限制,必须为非负整数,而且元素不宜过大. 算法思想: 设待排序序列的元素取值范围为0到m,则 ...

  7. 十大经典排序算法—桶排序

    1.算法思想: 桶排序是计数排序的升级版.它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定.为了使桶排序更加高效,我们需要做到这两点: 在额外空间充足的情况下,尽量增大桶的数量 使用的映 ...

  8. 桶排序算法(基于Java实现)

    title: 桶排序算法(基于Java实现) tags: 桶排序算法 桶排序算法的原理和代码实现 一.桶排序算法的原理 桶排序,顾名思义,会用到"桶",核心思想是将要排序的数据分到 ...

  9. JavaScript算法——桶排序

    一.桶排序的原理 桶排序是计数排序的升级版.它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定.思路大致是, 设置一个定量的数组当作空桶: 遍历输入数据,并且把数据一个一个放到对应的桶里去 ...

最新文章

  1. jquery 获取一组元素的选中项 - 函数、jquery获取复选框值、jquery获取单选按钮值...
  2. python3 安装 mysql 用pip install PyMySQL
  3. 新买的笔记本电脑怎么分盘_笔记本电脑该如何保养,延长使用寿命
  4. python客户价值分析_[Python数据挖掘]第7章、航空公司客户价值分析
  5. [转] Oracle学习之创建数据库(新建实例)
  6. Python 数据类型 布尔类型
  7. nginx 配置https_nginx 配置https
  8. UVA434 Matty‘s Blocks【贪心】
  9. 进程间通信 --- 命名管道 有名管道存在与内存中,无名管道存在与文件系统中 换种角度看问题
  10. ios开发错误之: Undefined symbols for architecture x86_64
  11. 【NLP】统计自然语言处理(第2版)思维导图
  12. 电力拖动自动控制系统_建筑电气控制系统安装
  13. Windows 10 自带的远程协助工具 快速助手
  14. 华为防火墙-管理配置
  15. 闪电Android视频转换器,闪电Android视频转换器
  16. Linux Shell
  17. EXCEL 删除表格内的空格和空白字符
  18. 退休当月要干到月底吗_到退休年龄,是当月办理退休,还是提前一个月办理?...
  19. 一不小心就触碰红线...程序员必须知道的法律知识有哪些?
  20. Android问题集锦(六)- adb不是内部或外部命令解决方法

热门文章

  1. php mail函数_PHP发送电子邮件函数mail详解
  2. vue中的minix
  3. MySQL基础入门学习【1】基本操作
  4. 微服务 Rpc和Rest协议
  5. 51CTO学院薛大龙软考班,再努力一点点就能成功了
  6. 精品软件 推荐 ESET Smart Security
  7. 了解你所不知道的SMON功能(十二):Shrink UNDO(rollback) SEGMENT
  8. 【原】开源——基于文件驱动的站点开发
  9. Java各版本的重大改变
  10. 图文详解 23 种设计模式