既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果要排序的数据有 n 个,我们把它们均匀地划分到 m 个桶内,每个桶里就有 k=n/m 个元素。每个桶内部使用快速排序,时间复杂度为 O(k * logk)。m 个桶排序的时间复杂度就是 O(m * k * logk),因为 k=n/m,所以整个桶排序的时间复杂度就是 O(n*log(n/m))。当桶的个数 m 接近数据个数 n 时,log(n/m) 就是一个非常小的常量,这个时候桶排序的时间复杂度接近 O(n)。
那既然桶排序这么的优秀,为什么我们在平时的使用中却偏向于其他的排序方法呢(大多数情况下偏向于时间复杂度为O(nlogn)的快排)?
桶排序的小缺点
桶排序对要排序数据的要求是非常苛刻的。
首先,要排序的数据需要很容易就能划分成 m 个桶,并且,桶与桶之间有着天然的大小顺序。
其次,数据在各个桶之间的分布是比较均匀的。如果数据经过桶的划分之后,有些桶里的数据非常多,有些非常少,很不平均,那桶内数据排序的时间复杂度就不是常量级了。
桶排序比较适合用在外部排序中。所谓的外部排序就是数据存储在外部磁盘中,数据量比较大,内存有限,无法将数据全部加载到内存中。
比如说我们有 10GB 的数据,我们希望对这波数据进行排序,但是我们的内存有限,只有1G,没办法一次性把 10GB 的数据都加载到内存中。这个时候该怎么办呢?
我们可以先扫描一遍文件,看数据所处的数据范围。假设经过扫描之后我们得到,数据最小为1,最大为1000。我们将所有数据划分到 100 个桶里,第一个桶我们存储在 1 元到 10 元之内的数据,第二桶存储在 11 元到 20 元之内的数据,以此类推。每一个桶对应一个文件,并且按照数据范围的大小顺序编号命名(00,01,02…99)。
理想的情况下,如果数据均匀分布,那数据会被均匀划分到 100 个文件中,每个小文件中存储大约 100MB 的数据,我们就可以将这 100 个小文件依次放到内存中,用快排来排序。等所有文件都排好序之后,我们只需要按照文件编号,从小到大依次读取每个小文件中的数据,并将其写入到一个文件中。
不过呢,不均匀才是常态嘛,有可能某个区间的数据特别多,划分之后对应的文件就会很大,没法一次性读入内存。这又该怎么办呢?
针对这些划分之后还是比较大的文件,我们可以继续划分。
如果划分之后,数据还是太多,无法一次性读入内存,那就继续再划分,直到所有的文件都能读入内存为止。
计数排序其实是桶排序的一种特殊情况。
还是上面那个例子来说,区间跨度为1000,那就分它一千个桶,每一个数据位一个桶。
我们就当这波数据都是整数,所以并不需要再进行排序。我们只需要依次扫描每个桶,将桶内的数据依次输出到一个文件中,就实现了 10G 数据的排序。因为只涉及扫描遍历操作,所以时间复杂度是 O(n)。
计数排序的小缺点
那这不也很明显嘛,我桶排序就开100个桶,运气不好多开几个,计数排序一上来就是1000个桶预订了,其中会有多少浪费,多少空桶,谁知道呢?
计数排序只能用在数据范围不大的场景中,如果数据范围 k 比要排序的数据 n 大很多,就不适合用计数排序了。而且,计数排序比较适合给非负整数排序(不然刚刚为什么要假设),如果要排序的数据是其他类型的,要将其在不改变相对大小的情况下,转化为非负整数。
我们再来看这样一个排序问题。假设我们有 10 万个手机号码,希望将这 10 万个手机号码从小到大排序,你有什么比较快速的排序方法呢?
这十一位的数,桶一个我看看?
不好分桶吧,跨度太大了。
我们可以用这样一种方法:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
13a03fab5e56a57acb)**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!