• 如何在很大数量级的数据中(比如1个亿)筛选出前10万个最小值?之七


    数据继续增加,麻烦很多。下面给出一个方案:

    void shift(int data[], int i, int length)                       //筛选算法
    {
      for(int c; c= i* 2+ 1, c< length; )
        if(c+= c+ 1< length && data[c]< data[c + 1], data[i]<= data[c])
          swap(data[c], data[i]),     i= c;
        else
          break;
    }
    //----------------------
    #define   i1K                 1024
    #define   i1M                 i1K* i1K
    #define   BlockSize           (100*i1M)
    void GetTopK(int sele, int All)
    {
      double times[3]= { GetTickCount() };
    
      int *Data0= new int[sele], *Data1= new int[BlockSize], File0Number;
      String path= "D:\", name= "inFile.dat";
      //第一步,打开或文件不存在时,做出随机数据文件。
      if(File0Number= open(String(path+ name).c_str(), 0), File0Number== -1)
      {
        File0Number= creat(String(path+ name).c_str(), 2);
        for(int all= All, size= BlockSize; all> 0; all-= size)      //减去做好的
          for(int i= 0; i<= size; i++)
            if(i== size)
              _rtl_write(File0Number, Data1, min(size, all));       //写出一块数据
            else
              Data1[i]= random(BlockSize);                          //得随机数
        lseek(File0Number, 0, SEEK_SET);                            //回文件首
      }
      times[0]= GetTickCount()- times[0];
      times[1]= GetTickCount();
      //第二步,取出数据。
      _rtl_read(File0Number, Data0, sele);
      for(int i= (sele- 2)/ 2; i>= 0; i--)
        shift(Data0, i, sele);                                      //建堆
      for(int i, size= 1; size> 0; )
        for(size= _rtl_read(File0Number, Data1, BlockSize), i= 0; i< size; i++)
          if(Data0[0]> Data1[i])                                    //小值
            Data0[0]= Data1[i],   shift(Data0, 0, sele);            //加小值,再成堆
      times[1]= GetTickCount()- times[1];
      times[2]= GetTickCount();
      //第三步,验证()
      //略
      times[2]= GetTickCount()- times[2];
    delete []Data0; delete []Data1; }

      它先判断是否有原始数据文件。无则创建并写入随机数据。

    再取出sele个数据。建最大堆。继续读出数据块。并逐步挑出最小数。

    程序看起来,还是很简单的。但,有两个问题:

    1、int 数的表达范围,只有二十亿。程序应该考虑数的表达范围问题了。

    2、验证有麻烦:之前,我们①用标准排序与结果比较。②还可用结果中的最大数,与取值后余下的数做比较,要是得到这个最大数都小于或等余下的数,就证明结果是正确的。现在,数太多,没法用标准排序。而取数后的数,还是保留在原始数据中。也就不能用法②。

    暂时就这样了。待想出验证办法再说。

  • 相关阅读:
    Spring中的destroy-method方法
    github Pull Request合入全流程介绍
    vue-router动态路由设置参数可选
    github上fork原项目,如何将本地仓库代码更新到最新版本?
    github的pull Request使用
    vue2.X版本vue-cli生成项目后运行失败,报错信息为getaddrinfo ENOTFOUND localhost
    npm在linux即mac下更新时报错
    数组Array和字符串String的indexOf方法,以及ES7(ES2016)中新增的Array.prototype.includes方法
    less的使用总结
    ssh连接github连不上
  • 原文地址:https://www.cnblogs.com/oldtab/p/4465890.html
Copyright © 2020-2023  润新知