位图排序算法实践
一。算法介绍
排序算法是计算机专业必学的内容,教科书里介绍的像冒泡排序,插入排序,Shell排序,堆排序,快速排序等几种经典的排序算法,其中快速排序最为推荐和广为人知,其采用二分分组递归的方式,对数据巧妙而快速的排序,平均性能复杂度为NLogN,商用的代码库一般会使用快速排序(由于其最差性能复杂度为NN,像STL库里面的排序算法会结合插入排序和堆排序,使其最差性能复杂度也能达到NLogN)。但是除了这些教科书里面的算法,有没有其它的排序算法,排序算法的时间复杂度能不能突破理论上的极限NLogN呢?
经典的《编程珠玑》一书里对于长度在一定范围的不重复数字序列,介绍一款非常巧妙的算法位图排序,其时间复杂度达到惊人的N,很多了解通用排序算法的读者,听到的第一反应可能是大呼怎么可能!
且看位图排序算法的实践逻辑如下:
1)第一步:申请一个长度超过最大数字的数组,
2)第二步:遍历数字序列,以数字作为索引,将数组对应的值赋值为1。
3)第三步:遍历数组,打印值为1的数组索引值
这个算法直接打破常规思维,唤山不来,向山走去,利用空间换取时间,使算法复杂度达到了不可思议的N,简单至极而又巧妙至极!二。编程实践
纸上得来终觉浅,绝知此事要躬行,位图排序的实际效果到底如何,笔者开发了一个demo来验证一下,代码中使用Java的里面的位操作来实现位图存储,以节约了存储空间,另外和快排排序算法进行了性能比较,代码如下:publicstaticvoidmain(String〔〕args){finalintMAX1000000000;数字最大值finalintCOUNT300000000;数字个数System。out。println(排序个数:COUNT);int〔〕intsgetRandomData(COUNT,MAX);longstartSystem。currentTimeMillis();startSystem。currentTimeMillis();intsgetRandomData(COUNT,MAX);startSystem。currentTimeMillis();quickSort(ints);System。out。println(快速排序时间:(System。currentTimeMillis()start));intsgetRandomData(COUNT,MAX);startSystem。currentTimeMillis();byte〔〕bytesbitmapSort(ints,MAX);System。out。println(位图排序1时间:(System。currentTimeMillis()start));}产生最大为值max,数量为count的数字privatestaticint〔〕getRandomData(intcount,intmax){int〔〕intsnewint〔count〕;for(inti0;icount;i){intran(int)(Math。random()max);System。out。print(ran);ints〔i〕ran;}returnints;}位图排序法1,无法处理重复数据privatestaticbyte〔〕bitmapSort(int〔〕array,intmax){finalintlen(int)Math。ceil(max8。0);byte〔〕bytesnewbyte〔len〕;for(inti0;iarray。length;i){intjarray〔i〕3;intkarray〔i〕8;bytes〔j〕setByte(bytes〔j〕,k);}returnbytes;}将字节b第i位置1publicstaticBytesetByte(byteb,inti){b0x01i;returnb;}快速排序paramarraypublicstaticvoidquickSort(int〔〕array){intlen;if(arraynull(lenarray。length)0len1){return;}sort(array,0,len1);}快排核心算法,递归实现paramarrayparamleftparamrightpublicstaticvoidsort(int〔〕array,intleft,intright){if(leftright){return;}base中存放基准数intbasearray〔left〕;intileft,jright;while(i!j){顺序很重要,先从右边开始往左找,直到找到比base值小的数while(array〔j〕baseij){j;}再从左往右边找,直到找到比base值大的数while(array〔i〕baseij){i;}上面的循环结束表示找到了位置或者(ij)了,交换两个数在数组中的位置if(ij){inttmparray〔i〕;array〔i〕array〔j〕;array〔j〕tmp;}}将基准数放到中间的位置(基准数归位)array〔left〕array〔i〕;array〔i〕base;递归,继续向基准的左右两边执行和上面同样的操作i的索引处为上面已确定好的基准值的位置,无需再处理sort(array,left,i1);sort(array,i1,right);}
对于最大10亿的3亿个数字排序:运行的时间结果是:
快速排序:37183毫秒
位图排序:4019毫秒
比起经典的快速排序,位图排序的性能要高出9倍以上!
但这个算法存在一个问题,就是排序的数字序列不能有重复的数字,如何改进这个算法呢?其实很简单,只要将存储最小单元由BIT改成BYTE,相同的数字,位图数组的值加1即可,这样可以处理最多255个重复的数,应该可以满足大部分场景,改进的代码如下:位图排序法2,可处理重复最多255个数privatestaticbyte〔〕bitmapSort2(int〔〕array,intmax){byte〔〕resultnewbyte〔max〕;for(inti0;iarray。length;i){result〔array〔i〕〕;}returnresult;}
运行测试,第二种排序时间为4857毫秒,效率依然杠杠的!
生活中的学习名言当你还不能对自己说今天学到了什么东西时,你就不要去睡觉。人天天都学到一点东西,而往往所学到的是发现昨日学到的是错的。生活就像海洋,只有意志坚强的人,才能到达彼岸。……
2020年我的奇思妙想优秀作文导语:我每天都有不同的奇思妙想,不知道你们是不是也跟我一样呢?接下来小编整理了2020年我的奇思妙想优秀作文,文章希望大家喜欢!2020年我的奇思妙想优秀作文1每个人都会……
我的梦想每个人都有梦想,都希望有一天会梦想成真,我曾经有过很多梦想,从小到大,有过很多很多这样那样的梦想,有很多我都放弃了,我从来没有坚持下去过,这次我真的坚持了,这是我最大的梦想,我……
为什么华为手机市场没有王者荣耀?今天在华为应用市场里搜索了一下,确实找不到《王者荣耀》这款游戏。我认为有几下几个原因:一、在华为应用市场里下载的软件,大部分都支持华为账户登录,而王者荣耀不同……
为什么现在人们都打微信语音电话,而不打手机电话了?这个我没计算打微信电话和打手机电话哪个更划算,只是微信电话方便些。打微信电话可以免费,打手机电话还要花钱。因为流量可以用套餐,或者兑换免费的流量券,这样流量可以不花钱,打……
淘宝上有骗子店铺,我深深上了一课,你经历过吗?我六月份在淘宝上买了一款绞肉机,九阳牌,付过款后才发现付货期限两个月,一直等了两个多月,未收到货,无奈要求退款,发起两次退款申请,均遭拒绝,耗不起时间了,决定卸载淘宝已经……
镜子里的爱,比金子贵重妻子躺在丈夫身边说:ldquo;哎!我说,你爹现在这样我可不伺候了,你看看一转身的功夫又拉满床。rdquo;丈夫心烦的翻了一下身说:ldquo;这还不都赖你,开始生病就应……
历史论文我心中的秦始皇ldquo;及至始皇,奋六世之余烈,振长策而御宇内,吞二周而亡诸侯,履至尊而制六合,执敲扑而鞭笞天下,威振四海。rdquo;这是《过秦论》对秦始皇的描述。有许多影视作品,都将秦……
关于雪景的作文400字美丽的雪景雪后,那绵绵的白雪装饰着世界,琼枝玉叶,粉装玉砌,皓然一色,真是一派瑞雪丰年的喜人景象。关于雪景的作文400字内容如下。关于雪景的作文400字:美丽的雪景冬天的早晨……
金证股份中标千万级东盟跨境支付结算数字平台建设项目近日,金证股份成功中标千万级广西龙邦智慧口岸跨境电商公共数字交易平台系统建设项目,涵盖跨境电商、供应链金融、支付清算以及云原生平台等建设内容,成为金证股份配合国家一带一路倡议,……
以我和爷爷为题的作文7篇【篇一:我和爷爷】我一生中有许多喜欢的人,有爸爸妈妈,哥哥姐姐,弟弟妹妹,但我最喜爱的还是我的爷爷。我的爷爷是一位和蔼可亲的老人,今年已经83岁了。他高高的鼻梁、宽……
农村的年轻留守妈妈,白天晚上都在忙什么?我是农村人我对这方面是最有发言权的,在我们农村不外乎二种人,一种人是治家有道,克尽责守。另一种人麻麻目目的不治家。男人外出了天下是她的了,小孩不好好带,和别的男人鬼混。这两种人……