zoukankan      html  css  js  c++  java
  • 如何在很大数量级的数据中(比如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、验证有麻烦:之前,我们①用标准排序与结果比较。②还可用结果中的最大数,与取值后余下的数做比较,要是得到这个最大数都小于或等余下的数,就证明结果是正确的。现在,数太多,没法用标准排序。而取数后的数,还是保留在原始数据中。也就不能用法②。

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

  • 相关阅读:
    gain 基尼系数
    luogu P5826 【模板】子序列自动机 主席树 vector 二分
    牛客挑战赛39 树与异或 离线 树上莫队 树状数组 约数
    4.22 省选模拟赛 三元组 manacher 回文自动机
    4.22 省选模拟赛 最优价值 网络流 最大权闭合子图
    4.18 省选模拟赛 消息传递 树剖 倍增 线段树维护等比数列
    luogu P4008 [NOI2003]文本编辑器 splay 块状链表
    牛客挑战赛39 密码系统 后缀数组
    luogu P1526 [NOI2003]智破连环阵 搜索+最大匹配+剪枝
    luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并
  • 原文地址:https://www.cnblogs.com/oldtab/p/4465890.html
Copyright © 2011-2022 走看看