位图排序
先说些题外话吧,本来以为blogbus修护好了,上去之后依然是错误,系统错误。靠,晕死了。既然如此,我只能弃之了,改日把东西搬过来。
进入正题:位图排序。
说实话,说到排序,我们首先想到的肯定是那些常见的排序,比如:冒泡啊,插排,选择啊,快排,甚至归并、基数排序等。这个位图排序似乎没听过啊。是的,是比较新鲜,但也很novel的一个算法。我最初见它于《编程珠玑》13章。当时只知道有个位图排序,但是具体的原理内幕,搞不懂啊。于是我查了一下详情,果然找到了一些。看我一一道来:
首先,相比以上的排序方法,位图排序明显的优点就是空时双赢啊(时间和空间)。该算法100w的非负整数只需0.125M内存,而时间复杂度则为o(n)(what? 你没搞错吧),是的,我没搞错。确实是这样。
比如N=100w个数来排序,每个int占32位,100w个数需要多少int型数呢?N/32+1,那么需要数组int array[N/32+1]就能代表N位了。
好,接下来重点:用一个整型数组 array[n] 来实现对输入数据的排序工作。具体点就是:(1)初始化,将数组的每个元素清 0;(2)插入数据并实现排序,对于输入数据 i,置 array[i] 为 1; (3)输出排序结果,如果 array[i] 为 1,就输出整数 i
比如整数60吧,60/32=1,0%32=28,那么也就是要将array[1](供32位)的第28位置为1就表明60存在。
除以32 可使用 右移 5 位 ( i >> 5) 来实现, 对 32 取模, 可以通过 1 << ( i & 0x1f ) 来实现
#define N 1000000
#define base 32
#define shift 5
#define mask 0x1f
int array[N/base+1]
void set(int i) //置i位1
{
array[i>>shift] |=(1<<(i&mask));
}
void clr(int i) //i对应位置0
{
array[i>>shift] &=~(1<<(i&mask));
}
int test(int i)//测试i对应位是否为1
{
return array[i>>shift] &(1<<(i&mask));
}
以上是核心三项,你没输入一次,数据就已经在数组中排好序了。你可以试一下哦。
当然东西都是两面的,他好的一面也暗示了它若得一面了,说说他的局限吧:
(1)都是非负整数,(2)每个整数最多出现一次,(3)最大整数小于 N。