算法研究(二) bitmap在排序中的妙用

面对几百万非负整形数据的排序问题,传统排序算法因内存和时间效率不高而显得不足。通过分析数据特点——非负、不超过7位且无重复,采用位图策略能有效解决。设置与数据量相当的位图,读取文件数据时将对应位设为1,然后遍历位图输出未置0的数字,实现快速排序。此方法类似哈希,若数据有重复,可配合计数数组;若数据分布均匀且规模较小,可调整哈希桶大小并处理冲突;若数据局部收敛,则需考虑其他算法。
摘要由CSDN通过智能技术生成

题目:在一个文件中存放着几百万个非负整形数据,它们最大不超过7位,且无重复数据,现将该文件中的数据按升序进行排序。

对于排序,相信没人会陌生,已知的通用排序算法对于这个题目都显得有些力不从心,昂贵的内存开销(如果采用硬盘排序倒是可以减少内存开销,但时间上将耗费更多),巨大的时间耗费(这点是最不能接受的)。所谓的巧妙算法实际上都是分析问题的特点,针对它的特殊性而得出的。对于这个问题,有两个条件必须注意:一是数据非负且最大不超过7位;二是数据无重复。有了这两个条件,位图就可以派上用场了。

可以设置一个大小为1000万的位图,差不多相当于二十多万个整形的大小,它的每一位对应着一个最大不超过7位的数据,先清空该位图,然后从文件中读数据,将相应位置1。然后扫描位图,将非0位的对应数据输出到文件中去,整个过程便己完成,具体算法如下:

#define SIZEBIT 10000000
#define SIZE SIZEBIT/32 + 1

void cleanAll(unsigned int* bitmap) {

    int i;
    for (i = 0; i < SIZE; ++i)
        bitmap =0; 
}

void set(unsigned int* bitmap, unsigned int index) {
    bitmap[index/32] |= 1 << index%32;
}

void clean(unsigned int* bitmap, unsigned int index) {
    bitmap[index/32] &= ~(1 << index%32);
}

int get(unsigned int* bitmap, unsigned int index) {
    return bitmap[index/32] & (1 << index%32);
}

void sort() {
        unsigned int bitmap[SIZE];
        cleanAll(bitmap);

        FILE *fp = fopen("sortFile.txt", "r");
        unsigned int data;
        while (EOF != fscanf(fp, "%d", &data)) {
            set(bitmap, data);
        }
        fclose(fp);

        fp = fopen("sorted.txt", "w");
        int i;
        for (i = 0; i < SIZEBIT; ++i) {
            if (get(bitmap, i))
                fprintf(fp, "%d\n", i);
        }
        fclose(fp);
}

实际上这种思想有点类似于哈希,只不过哈希算法简单的成了VALUE=KEY而已。如果条件中允许重复,我们就需要额外弄一个count数组用于计算重复数据。而如果数据没有几百万那么大,但它分部的很均匀,我们仍可以使用这种算法,可以将哈希桶的大小弄得小一点,以减小内存开销,不过我们恐怕还得花费额外的精力去处理哈希冲突,可以考虑使用链表,然后使用插入排序算法。而如果数据的分部不是那么均匀,而是存在着大量的局部收敛,那么哈希冲突所带来的巨大的时间耗费便不是我们可以接受的了,就应该考虑其它算法思想了。

参考文献

《编程珠玑》(美)本特利(Bentley,J.)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值