zoukankan      html  css  js  c++  java
  • 位图排序

    输入:一个最多包含一百万(10^6)个正整数的文件,每个数都小于n,其中n=一千万(10^7)。输入文件中没有重复的整数。

    输出: 按升序排列这些数,并写入磁盘。

    约束:有 1MB多(不超过2MB) 的内存空间可用,有充足的硬盘空间

    一、原理

             这道题是在编程珠玑上看到的,是习题3,自己写了一下玩玩,感觉这个算法很棒,通俗易懂。

     这个问题的最好算法应当是位图:由于整数没有重复,那么可以用比特位来表示整数的存在。

    比如集合  {1,2,5,4,6},

    可以用位图表示为   01101110,

    由于位图的第1,2,4,5,6为都是1,表示集合里存在着这几个数。

    因为这个算法实现的时候,数最大为10 000 000,那么需要用10 000 000个bit的数组来表示,内存大小为 10 000 000/8/1024/1024约等于1.2M

    实现需要解决以下问题有:

    1) 找到数据i所对应的字节位置

    2)找到数据i对应的字节中位位置

    3) 判断某位是否为1, 置某位为1 

    解决它:

    1) 找到 对应字节位置: 32系统,相当于 i/32, 使用位操作 数据i >> 5

    2)  找到对应字节的位位置: 32系统相当于 i%32, 使用位操作 数据 i&0x1F(31)

       附:(m mod n 运算,当n = 2的X次幂的时候,m mod n = m&(n-1)  ,这里32为2^5,所以是i&0X1F)

     n=2^x 写成二进制就是1后面x个0,m%n就是m的低x位。 
    n-1=2^x-1 写成二进制是x个1,m&(n-1)也是取m的低x位。

    3)数字 a 的 第i位 是1: 方法 a & (1 << i) ,将数据a的第 i位 置1: a | (1 << i)

    二、代码

    (因为C++STL中有bitset这一容器,所以实现起来并不难,我先用bitset实现,后用C++不用bitset实现)

    /**************************************
    *                                     *
    *  -*- coding: utf-8 -*-              *
    *  @Date    : 2016-05-12 18:54:47     *
    *  @Author  : Zeroinger               *
    *                                     *
     *************************************/
    #include <iostream>
    #include <algorithm>
    #include <time.h>
    #include <bitset>
    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <sstream>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <cstdio>
    #include <algorithm>
    #include <fstream>
    using namespace std;
    #define MAXN 10000000
    #define NUM  1000000
    #define SHIFT 5
    #define MARK 0x1F
    #define DIGITS 32
    int a[MAXN+1];
    //bitset <MAXN+1> bit;
    int b[1+MAXN/32];
    void st(int i)
    {
        b[i >> SHIFT] |= (1 << (i & MARK));
    }
    
    int test(int i)
    {
        return b[i >> SHIFT] & (1 << (i & MARK));
    }
    
    void clr(int i)
    {
        b[i >> SHIFT] &= ~(1 << (i & MARK));
    }
    void write()
    {
    
        for(int i=0; i<=MAXN; i++)
        {
            a[i]=i+1;
        }
    }
    int getrand(int a,int b)
    {
        return  ((a+RAND_MAX * rand() + rand()) % (b-a+1));
    }
    void getdata()
    {
        for(int i=0; i<NUM; i++)
        {
                int t=getrand(i,MAXN);
                swap(a[i],a[t]);
        }
        FILE *fp;
        fp = fopen("test_before.txt", "w");
        if(fp == NULL)
        {
            cout << "随机数文件生成失败,error in make_data()." << endl;
        }
        int cc=0;
        for(int i = 0; i < NUM; i++)
        {
            fprintf(fp, "%7d  ", a[i]);
            cc++;
            if(cc%20==0)
            fprintf(fp, "
    ");
    
        }
        cout<<cc<<endl;
        fclose(fp);
        cout << "随机数文件生成成功." << endl;
    }
    int main()
    {
       // bit.reset();
       for(int i=0;i<MAXN;i++)
       {
           clr(i);
       }
        write();
        getdata();
        FILE *fpsrc;
        fpsrc = fopen("test_before.txt", "r");
        if(fpsrc == NULL)
        {
            cout << "打开文件失败" << endl;
            return 0;
        }
    
        int data;
        while(fscanf(fpsrc, "%d", &data) != EOF)
        {
    
               // bit.set(data,1);
               st(data);
    
        }
        FILE *fpdst;
        fpdst = fopen("test_after.txt", "w");
        if(fpdst == NULL)
        {
            cout << "打开文件失败" << endl;
            return 0;
        }
        int c=0;
        for(int i = 0; i <MAXN+1; i++)
        {
            if(test(i)/*bit[i] == 1*/)
            {
                fprintf(fpdst, "%7d ", i);
                c++;
                if(c%20==0)
                  fprintf(fpdst, "
    ");
    
            }
        }
        cout<<c<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    javascript:history.go()和history.back()的区别
    ASP.NET26个性能优化方法
    20 个 jQuery 分页插件和教程,附带实例
    JQuery中$.ajax()方法参数详解
    记住键盘快捷键大全 提高电脑操作速度
    URL重写案例
    url重写(伪静态)IIS配置图解
    URL重写的优缺点分析
    C# GUID的使用
    js中的编码与解码
  • 原文地址:https://www.cnblogs.com/Zeroinger/p/5495410.html
Copyright © 2011-2022 走看看