zoukankan      html  css  js  c++  java
  • 海量数据处理:一亿个浮点数的排序算法

    有1亿个浮点数,请找出其中最小的10000个。提示:假设每个浮点数占4个字节,1亿个浮点数就要站到相当大的空间,因此不能一次将全部读入内存进行排序。
    问题分析:
    1) 1亿个浮点数,其数据大小为 400 M。如此规模的排序,首先想到分批处理。每次读取 1 000 000 个数据并进行快速排序。需要的内存空间为 1 000 000 * 4  = 4M。需要100 次这样的排序。

    2)完全没的规律的数据,考虑使用快速排序。快速排序的平均复杂度是 O( Nlog(N) )。我们可以直接使用 stl 提供的全局函数 sort() , 它使用了快速排序算法(实际是三平均分区法 median-of-three )。
    3) 最后只要最大的 10000 个。则每个批次只需要保留排序结果的前 10000 个数据。这段数据已经是分段有序的。数据量为 10000 * 100。
    解法:
    1) 数据结构定义:
    定义数据规模:

    enum
    {
        batchCapacity 
    = 1000000,
        batchCount    
    = 100,
        resultCount    
    = 10000
    }


    2)生成 数据样本:


    void dataPrepare( const char* filName  )
    {
        
    float* pbuf;
        
    if( ( pbuf= (  float *)malloc( batchCapacity  * sizeoffloat ) )) == NULL )
        {
            
    throw"failed to malloc" );
        }
        
    //  生成 batchCapacity * batchCount 个随机实数,并保存到文件 
        ofstream fout;
        fout.exceptions(std::ios::badbit 
    | std::ios::failbit | std::ios::eofbit );
        fout.open( filName, ios::binary ) ;
        
    if ( !fout   )
        {
            
    throw"file not exits" );
        }
        
    for( size_t index = 0; index < batchCount; index++ )
        {
            
    for( size_t index = 0; index < batchCapacity; index++  )
            {
                pbuf[index] 
    = RandomFloat( 065537 );
            }
            fout.write( (
    char*)pbuf, batchCapacity * sizeoffloat )  );
        }
        fout.close();
        delete pbuf;
        pbuf 
    = NULL;
        
    return ;
    }


    以上,用 RandomFloat() 生成随机数。其定义如下:

    /********************************************
     * Rand::rand 线性同余算法获得随机数
     * 会循环出现相同的数。有待改进
     *
     ********************************************
    */

    #include 
    <cstdlib>
    #include 
    <ctime>
    class Rand
    {
    public:
        
    static long long r;
        
    static int rand()//产生随机数
        {
           // 三个参数的取值 关键字:辗转相除 二次同余
            r = ( r * 1010557   + 79390691  ) %  100663363 ;
     
            
    return r;
        }
    };
    long long Rand::r = 43215;

    float RandomFloat( float low, float high) {
        
    float d = float( Rand::rand()) / ( float(RAND_MAX) + 1);
            
    return low + d * (high - low);
    }

    3 ) 排序


    void dataOrder( const char* filName  )
    {
        
    float* pbuf  = (  float *)malloc( batchCapacity  * sizeoffloat ) );
        
    if ( pbuf == NULL )
        {
            
    throw"failed to malloc " );
        }
        ifstream fin;
        ofstream fout;
        fin.exceptions(std::ios::badbit 
    | std::ios::failbit | std::ios::eofbit );
        fout.exceptions(std::ios::badbit 
    | std::ios::failbit | std::ios::eofbit );
        fin.open( filName, ios::binary );
        fout.open( 
    stringstring(filName).append(".order") ).c_str(), ios::binary ); 
        
    for( size_t index = 0;index < batchCount;index++ )
        {
            
    // 分批读入,排序
            fin.read( (char*)pbuf, batchCapacity * sizeoffloat )  );
            std::sort( pbuf, pbuf 
    + batchCapacity );
            fout.write( (
    char*)pbuf,  resultCount * sizeoffloat ) );
            cout 
    <<  "writed bytes:"  << resultCount * index + 1 <<  endl;
        }
        fin.close();
        fout.close();
        delete pbuf;
        
    // 将分组的数据综合排序
        pbuf =  (  float *)malloc( resultCount * batchCount * sizeoffloat ) );
        
    if ( pbuf == NULL )
        {
            
    throw"failed to malloc " );
        }
        fin.open( 
    stringstring(filName).append(".order") ).c_str(), ios::binary ); 
        fin.read( (
    char*)pbuf, resultCount * batchCount * sizeoffloat )  );
        std::sort( pbuf, pbuf 
    +  resultCount * batchCount  );

        
    //merge_sort<float>(  pbuf,0,( resultCount *  batchCount ) - 1 );
        
    // 输出
        for(  size_t index = 0; index < resultCount; index++ )
        {
            printf( 
    "%d\t%f\n",  index, pbuf[index ] );
        }
        fin.close();
        delete pbuf;
        pbuf 
    = NULL;
    }


    性能测试结果: p4 的 cpu,每秒大约处理 30万个记录。
    整个程序:

    const char* filName = "c:\\float.df";
    void dataPrepare( const char* filName  );
    void helpInfo();
    void dataOrder( const char* filName  );
    int main( int argc, char* argv[] )
    {
        
    try
        {
            
    if  ( argc == 1 )
            {
                helpInfo();
                
    return 0;
            }
            
    const char* filename = argv[1]+ 2;
            
    if ( filename != NULL && strlen( filename ) > 0 )
            {
                filName 
    = filename;
            }
            
    switch ( argv[1][1] )
            {
            
    case 'g':
                dataPrepare( filName  );
                
    break;

            
    case 'o':
                dataOrder( filName  );
                
    break;
            
    default:
                helpInfo();
                
    return 0;
                
    break;
            }
        }
        
    catch(  const char* e)
        {
            cout 
    <<  e << endl;
        }
        
    catch(    )
        {
            cout 
    <<  "unknown error" << endl;
        }
        system( 
    "pause" );
        
    return 0;
    }



    Referance:
    快速排序
    the c++ programming lanauage, by bjarne stroustrup chapter 18: Algorithms and Function Objects
    线性同余法生成随机数
    Introduction to Algorithms, Second Edition,by Thomas H. Cormen, Charles E. 11.3 Hash functions 介绍了线性同余法的原理和用法。

    三平均分区法:
    Introduction to Algorithms, Second Edition,by Thomas H. Cormen, Charles E. Problems 7-5: Median-of-3 partition


  • 相关阅读:
    关于同余最短路
    【水】关于 __attribute__
    题解【AtCoder
    一些简单图论问题
    浅谈简单动态规划
    关于博客园主题(美化博客园)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第47章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第46章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第45章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第44章 读书笔记(待更新)
  • 原文地址:https://www.cnblogs.com/diylab/p/1562407.html
Copyright © 2011-2022 走看看