算法、数据结构一直是自已薄弱的环节,一直想学习但觉得自己水平太臭,怕打击信心.平时工作中也只是会用库中的函数或类来解决问题。
逛书店无意间找到编程珠玑II,看了看目录感觉像小故事一样的来讲解算法,一下子就有了兴趣。俺们一比较喜欢的轻松一类的书籍比如: 《大话设计模式》、 《走出软件作坊》、《head first》系列( 好是好就是有点贵呀!) 。
带回家后看了第一章就被作者神奇的排序方法所折服,真是太神奇了。
简述一下问题:电话号码排序
电话号码来自于一个外部文件中,电话号码是个数在上百万个且不重复,要求是将这个文件中的电话号码排序,输出到另一个文件,排序算法中内存使用不超过1M,时间在几分钟内,最好在10秒即可。
我思前想后,想不出来办法,我以往的做法是:将电话号码放入一个数组、或链表、容器中,然后使用冒泡法排序或快速排序。现在的电脑内存一般够大,直接放进来就是。但是现在有要求了,内存不能多用,时间还得快。
我实在想不出来,看作者用的是什么高招: 位图或称为位向量表,这是什么意思呢?下面举个下下列子。
1字节为8位,每一位只能用0,1来表示。
如果排序:n[] ={1,3,5,7}这几个数字,我们使用一个字节的位图来表示为:01010101 其中:
第1位的0表示数字0,在数组n中没有0所以这一位为0,
第2位的1表示数字1,在数组n中有1所以这一位为1.
第3位的0表示数字2,在数组n中没有2所以这一位为0
第4位的1表示数字3,在数组n中有3所以这一位为1.
以下依此类推。
我们将01010101 为1的位的序号依次输出,及为排序后的效果.其中升序、降序只需要循环方向就行了。
按以上的数据结构来表示就可以解决内存问题了,排序只是按位向量表输出即可,根本没什么运算。时间主要消耗在了对文件的读、写上面了。
以下是delphi主要代码:
上面delphi代码在我的电脑上执行:5百万个34秒、1百万个是6.8秒
C++实现方式:
上面C++代码在我的电脑上执行还是debug版的:1百万个是4.2秒, C++用的不太会,编译成release版后的一闪而过连我控制台的输出都看不到,可能是优化的太过了吧!!
上面对文件的读写都是以二进制的方式没有保存为ASCII码,这是为了测试算法速度,减少读出字符串后将字符串转换为整数,又在写入文件时将整数转换为字符串。
下面代码是用delphi生成一个数据文件的工具,包含了对上面TSortInteger类的使用。