桶排序

十大经典排序排序算法学习总结(C++实现)

倖福魔咒の 提交于 2020-02-07 21:48:55
常用算法总结记录一下,否则会变得只记得算法名,也可能名都记不住。 图片和动图(我不会画),但我从网上找到了资源。 代码我用C/C++实现的,运行结果都有验证。 时间复杂度和空间复杂度我还没有研究,各种地方抄到的,以后有时间再研究,如果有错误,还请指正。   In/out-place: 不占/占额外内存 1.冒泡排序  冒泡排序算法原理:   比较相邻的元素。如果第一个比第二个大,就交换他们两个。   循环重复以上步骤,直到没有任何一对元素需要比较。   还有位前辈也画的挺好,我也把图贴过来了。  冒泡排序时间复杂度、空间复杂度、稳定性   冒泡排序时间复杂度:最好 O( n) 最坏 O( n 2 ) ,平均 O( n 2 ) 。   冒泡排序空间复杂度: O( 1 ) 。   冒泡排序是一种 稳定 排序算法。  冒泡排序源码实现 1 #include <iostream> 2 using namespace std; 3 4 5 template <typename T> 6 void BubbleSort(T arr[], int len) 7 { 8 if (NULL == arr || 0 >= len) 9 return; 10 11 int i = 0, j = 0, nFlag = 0; 12 13 for (i = 0; i < len - 1; i++) 14 {

【海量数据处理】100亿个整数,内存足够,如何找到中位数?内存不足,如何找到中位数?

余生长醉 提交于 2020-02-02 01:08:00
内存足够的情况: 可以使⽤用类似quick sort的思想进行,均摊复杂度为O(n),算法思想如下: • 随机选取一个元素,将比它小的元素放在它左边,比它大的元素放在右边 • 如果它恰好在中位数的位置,那么它就是中位数,可以直接返回 • 如果小于它的数超过一半,那么中位数一定在左半边,递归到左边处理 • 否则,中位数一定在右半边,根据左半边的元素个数计算出中位数是右半边的第几大,然后递归 到右半边处理 内存不足的情况: 无重复数字:   bitmap方法 有重复数字:   既然要找中位数,很简单就是排序的想法。那么基于字节的桶排序是一个可行的方法 :   思想:将整形的每1byte作为一个关键字,也就是说一个整形可以拆成4个keys,而且最高位的keys越大,整数越大。如果高位keys相同,则比较次高位的keys。整个比较过程类似于字符串的字典序。   第一步:把10G整数每2G读入一次内存,然后一次遍历这536,870,912个数据。每个数据用位运算">>"取出最高8位(31-24)。这8bits(0-255)最多表示255个桶,那么可以根据8bit的值来确定丢入第几个桶。最后把每个桶写入一个磁盘文件中,同时在内存中统计每个桶内数据的数量,自然这个数量只需要255个整形空间即可。   代价:(1) 10G数据依次读入内存的IO代价(这个是无法避免的,CPU不能直接在磁盘上运算)。

桶排序之计数排序与基数排序

大憨熊 提交于 2020-01-29 09:28:55
桶排序之计数排序和基数排序 桶排序 一种常见的排序算法,工作原理是将数组分到有限数量的桶子里,每个桶子再个别进行排序(会使用递归的方式继续使用桶排序进行排序或者使用其他的排序算法). 计数排序 计数排序是桶排序的一种特殊情况 从图中可以看出,待排序数字在[1,9]范围内; 创建9个空桶,将待排序数字分别放在对应的桶中; 再依次将桶中的元素按照桶的顺序拿出; 代码实现: public class CountSort { public static void main ( String [ ] args ) { int [ ] arr = { 2 , 4 , 2 , 3 , 7 , 1 , 1 , 1 , 0 , 5 , 6 , 9 , 8 , 7 , 4 , 0 , 9 } ; int [ ] result = sort ( arr ) ; System . out . println ( Arrays . toString ( result ) ) ; } static int [ ] sort ( int [ ] arr ) { //新建一个数组用来存放最终的结果 int [ ] result = new int [ arr . length ] ; //10个桶 int [ ] count = new int [ 10 ] ; //计数,计算每个桶中有多少个数字 for (

动画 | 什么是基数排序?

大憨熊 提交于 2020-01-27 14:12:16
基数排序和计数排序一样无需进行比较和交换,和桶排序一样利用分布和收集两种基本操作进行排序。基数排序是把每一个元素拆成多个关键字,一个关键字可以在每一个元素上同等的位置进行计数排序,一个元素拆成多个关键字可以看作是要进行几轮分桶,以一个元素最长的长度为准。 基数排序可以看成多(单)关键字的排序,可以想象成桶排序那样分桶排序,也可以像计数排序那样归约化分治。 基数排序的思想是将待排序序列中的每组关键字进行桶排序。例如整数序列[103, 9, 1,7,11,15, 25, 201, 209, 107, 5]上每个位、十位和百位上的数字看成是一个关键字。 基数排序有两种方式进行,一种是LSD,从右边关键字开始排序,另一种是MSD,从左边关键字开始排序。 基数排序LSD 我们将输入数组[103, 9, 1,7,11,15, 25, 201, 209, 107, 5],从右边关键字开始,以个位数上开始分桶,对于数字,每一个关键字取值范围是0~9,最多需要10个桶。如果是字符,按ASCII码最多需要128个桶,看情况而定。 为了保证元素之间的稳定性,就按计数排序一样,将给出一个统计数组c,长度为10,统计输入数组每一个元素对应的关键字。然后从统计数组c第2个位置开始,进行当前一项和前一项的累加。累加完之后反向填充数组b,也将数组b直接复制到数组array。 再进行循环操作exp *= 10

桶排序

女生的网名这么多〃 提交于 2020-01-27 04:57:51
桶排序 快速桶排序就是先创建出来一个一维数组,并把这个数组当中的变量都初始为0,然后把数组当中每个与输入数据相同的编号的变量加一,然后把数值大于等于1的变量按照从大到小或者从小到大的顺序都打印出来。 当然这样说的话,学程序的人是能够看一下就大概明白我说的是什么了,但是放假前老师对我的要求是让我能讲出来,并且让别人能够简单明了的看懂,这就让我很为难了,不过这也确实是一个不错的学习方法,所以我想到的并且能够做到的办法就是换个说法: 首先定义一个数组(或者说先拿一些小水桶?),数组当中每个变量就相当于一个桶。 “每个与输入数据相同的编号的变量加一”的意思就是数组当中的每个变量都有一个编号,对吧?例如:a[5],a[8]。上面那句话就是如果输入的数据当中如果有5或者8的话,就让数组当中的a[5],a[8]的值加一。 当然这样说的话就是偏向于学术说法了,那我换个说法,你刚才拿过来了一些小水桶对吧?咱们就假设那些水桶上都有着属于自己的编号,比如:1,2,3,4,5等等。 然后你手里有一些小弓箭,当然这些弓箭上也有着编号,然后你要做的就是找到和弓箭上编号相同的小水桶,并把对应的弓箭放进去。 “值加一”的意思就是,你放进去一个弓箭那个小水桶里就有一个弓箭,你再放一个,那么就有两个弓箭,或许这样的说法,你可能会说我是在说废话,但是这就是在实现“值加一”的方式

LeetCode 164. Maximum Gap (排序)

≡放荡痞女 提交于 2020-01-22 19:25:51
题目 题意:就是给你一个数组,让你输出排好序后,相邻元素差值最大的那个差值。 题解:首先,当然我们可以用快排,排完序之后,遍历一遍数组,就能得到答案了。但是快速排序的效率是O(n* logn),不是题目要求的线性效率,也就是O(n)的效率。 那么诸多排序算法中,也是由线性效率的排序算法,当然这些算法的目标是线性效率,而在实际情况中的效率也并不是最快的。首先就是基数排序,基数排序的效率是O(n*k), k 是由元素的位数决定的。 线性时间的排序还有一个桶排序,桶排序,一开始选择一些桶,每个桶代表一个范围区间,把数字按部就班放到桶里,然后在桶里再继续排序,(可以继续递归用桶排序,也可以用别的排序)。 在这道题目中,桶排序是最好的选择,因为如果使用桶排序,则无需将整个数组都排序,题目要求的是排好序之后的相邻元素的最大差值。 假设最小值是min,最大值是max,数组的个数是n。那么假设这n个数字在min和max之间平均分布, k = (min-max)/(n-1) 代表相邻元素之间的差值。现在假设n个数字不是平均分布的,就是任意哪种情况,那么相邻元素之间的差值永远都是大于K的,这是可以证明的。所以确定了min,max,n,那么相邻元素的最大差值都是必定大于等于k的。 所以我们的每个桶的大小(区间范围)设为k,这样答案就在桶和桶之间,而不存在桶里,所以我们在第一次按部就班的放到桶里之后

【一周一算法】小哼买书

筅森魡賤 提交于 2020-01-16 05:37:25
之前讲了三种常用的经典排序。排序算法还有很多,例如选择排序、计数排序、基数排序、插入排序、归并排序和堆排序等等。堆排序是基于二叉树的排序,以后再说吧。先分享一个超酷的排序算法的视频。 再来看一个具体的例子《小哼买书》来看看三个排序在应用上的区别和局限性。 小哼的学校要建立一个图书角,老师派小哼去找一些同学做调查,看看同学们都喜欢读哪些书。小哼让每个同学写出一个自己最想读的书的ISBN号(你知道吗?每本书都有唯一的ISBN号,不信话你去找本书翻到背面看看)。当然有一些好书会有很多同学都喜欢,这样就会收集到很多重复的ISBN号。小哼需要去掉其中重复的ISBN号,即每个ISBN号只保留一个,也就说同样的书只买一本(学校真是够抠门的)。然后再把这些ISBN号从小到大排序,小哼将按照排序好的ISBN号去书店去买书。请你协助小哼完成“去重”与“排序”的工作。 输入有2行,第1行为一个正整数,表示有n个同学参与调查(n<=100)。第2行有n个用空格隔开的正整数,为每本图书的ISBN号(假设图书的ISBN号在1~1000之间)。 输出也是2行,第1行为一个正整数k,表示需要买多少本书。第2行为k个用空格隔开的正整数,为从小到大已排好序的需要购买的图书ISBN号。 例如输入 10 20 40 32 67 40 20 89 300 400 15 则输出 8 15 20 32 40 67 89 300

数据结构——基数排序(算法)

末鹿安然 提交于 2020-01-16 01:53:59
基数排序(桶排序)介绍: 基数排序(radix sort)属于“分配式排序”,又称桶子法,它是通过键值的各个位的值,将要排序的元素分配到某些“桶”中,达到排序的作用 基数排序法是属于稳定性排序,基数排序法是效率高的稳定性排序法。 基数排序是桶排序的扩展。 基数排序是1887年赫尔曼·何乐礼发明的,它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较。 基本思想: 将所有待比较数值统一为同样数位长度,数位较短的数前面补0,然后从最低位开始,依次进行依次排序,这样从最低位排序一直到最高位排序完成以后,数列就变成了一个有序序列。 原理图 原理代码示例 private static void radixSort ( int [ ] array ) { /*定义一个二维数组,表示10个桶,每个桶是一位数组*/ /*说明: * 1、二维数组包含10个以为数组 * 2、为了防止在放入数据的时候,数据溢出,则每个一位数组(桶),大小定义为array.length * 3、基数排序是使用空间换时间的经典算法*/ int [ ] [ ] bucket = new int [ 10 ] [ array . length ] ; /*为了记录每个桶中,实际存放了多少个数据,定义一个一维数组记录每个桶中的数组个数 * eg:bucketElementsCount[0]

【坐在马桶上看算法】小哼买书

梦想的初衷 提交于 2020-01-14 13:41:36
之前讲了三种常用的经典排序。排序算法还有很多,例如选择排序、计数排序、基数排序、插入排序、归并排序和堆排序等等。堆排序是基于二叉树的排序,以后再说吧。先分享一个超酷的排序算法的视频。 再来看一个具体的例子《小哼买书》来看看三个排序在应用上的区别和局限性。 小哼的学校要建立一个图书角,老师派小哼去找一些同学做调查,看看同学们都喜欢读哪些书。小哼让每个同学写出一个自己最想读的书的ISBN号(你知道吗?每本书都有唯一的ISBN号,不信话你去找本书翻到背面看看)。当然有一些好书会有很多同学都喜欢,这样就会收集到很多重复的ISBN号。小哼需要去掉其中重复的ISBN号,即每个ISBN号只保留一个,也就说同样的书只买一本(学校真是够抠门的)。然后再把这些ISBN号从小到大排序,小哼将按照排序好的ISBN号去书店去买书。请你协助小哼完成“去重”与“排序”的工作。 输入有2行,第1行为一个正整数,表示有n个同学参与调查(n<=100)。第2行有n个用空格隔开的正整数,为每本图书的ISBN号(假设图书的ISBN号在1~1000之间)。 输出也是2行,第1行为一个正整数k,表示需要买多少本书。第2行为k个用空格隔开的正整数,为从小到大已排好序的需要购买的图书ISBN号。 例如输入 10 20 40 32 67 40 20 89 300 400 15 则输出 8 15 20 32 40 67 89 300

十大经典排序算法最强总结(含JAVA代码实现)(转载)

人走茶凉 提交于 2020-01-10 06:45:04
最近几天在研究排序算法,看了很多博客,发现网上有的文章中对排序算法解释的并不是很透彻,而且有很多代码都是错误的,例如有的文章中在“桶排序”算法中对每个桶进行排序直接使用了Collection.sort()函数,这样虽然能达到效果,但对于算法研究来讲是不可以的。所以我根据这几天看的文章,整理了一个较为完整的排序算法总结,本文中的所有算法均有JAVA实现,经本人调试无误后才发出,如有错误,请各位前辈指出。 0、排序算法说明 0.1 排序的定义 对一序列对象根据某个关键字进行排序。 0.2 术语说明 稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面; 不稳定 :如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面; 内排序 :所有排序操作都在内存中完成; 外排序 :由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行; 时间复杂度: 一个算法执行所耗费的时间。 空间复杂度 :运行完一个程序所需内存的大小。 0.3 算法总结 图片名词解释: n: 数据规模 k: “桶”的个数 In-place: 占用常数内存,不占用额外内存 Out-place: 占用额外内存 0.5 算法分类 0.6 比较和非比较的区别 常见的 快速排序、归并排序、堆排序、冒泡排序 等属于 比较排序 。 在排序的最终结果里,元素之间的次序依赖于它们之间的比较