简单模拟对大数据进行排序的整个过程

面试官特别喜欢问的一个问题是对大数据的处理。自己在面试之前也看过一些方法,如July大神等人的文章,但是实际面试时感觉答的还是不够好,感觉是因为自己没有真正实现这个问题。下面我就用最简单的方法模拟一个简单的大数据排序问题。

问题描述:有一个大文件(多个也可以)无法一次读入内存,需要对大文件中的内容进行排序(这里只考虑最简单的无符号整型的情况)。

方法概括:一行一行读取大文件,使用哈希将每一行的数据存入到一个小文件中,并且保证每个小文件中的数据是属于某个区间的(其实就是桶排序的过程)。然后依次读取每个小文件(假设小文件是可以一次性读入内存的),对其内容进行排序(针对这个问题,可能基数排序比较好,我使用的是最简单的快排)。最后将每个排序小文件的结果合并即可。

下面是实现的代码:

/**该项目模拟一个大数据排序的解决方案*/

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <random>
#include <algorithm>

using namespace std;

//模拟生成一个大数据文件,文件中是随机数,取值范围是[0, 99999]
class large_data_generater
{
public:
    large_data_generater() : filename("large_data.txt") {}
    large_data_generater(string name) : filename(name) {}
    void generate()
    {
        ofstream output(filename);
        uniform_int_distribution<unsigned> u(0, 99999);
        default_random_engine e; //可以生成均匀分布的unsigned类型的数据
        cout << filename << endl;
        for(int i=0; i<100; ++i)
        {
            for(int j=0; j<100; ++j)
            {
                output << u(e) << " "; //生成下一个随机数
            }
            output << endl; //一个100行,每行100个随机数
        }
        output.close();
    }
private:
    string filename;
};

//对大数据进行排序的类
class sort_large_data
{
public:
    sort_large_data() : filename("large_data.txt") {}
    sort_large_data(string name) : filename(name) {}
    void hash() //该方法将大文件分割成小文件,分别进行存储
    {
        ifstream input(filename); //无序大文件
        if(!input)
        {
            cerr << "Can not read file!" << endl;
            exit(1);
        }
        ofstream output[10];
        for(int i=0; i<10; ++i) //保存哈希结果的小文件
        {
            int p = filename.find('.');
            string small_file = filename.substr(0, p) + char(i + '0') + ".txt";
            output[i].open(small_file, ios::app);
        }
        string line;
        while(getline(input, line))
        {
            istringstream iss(line);
            unsigned int ui;
            while(iss >> ui)
            {
                auto num = ui / 10000; //使用最简单的哈希方法,可以将大文件分成10个小文件,并且每个文件中的数据属于某个区间
                output[num] << ui << " ";
            }
        }
        input.close();
        for(int i=0; i<10; ++i)
            output[i].close();
    }
    void sort() //该方法读取每个小文件,进行排序后写到一个大文件中
    {
        int p = filename.find('.');
        string sortfile = filename.substr(0, p) + "_sort.txt"; //保存排序结果的文件
        ofstream output(sortfile);
        ifstream input[10];
        for(int i=0; i<10; ++i) //打开小文件
        {
            int p = filename.find('.');
            string small_file = filename.substr(0, p) + char(i + '0') + ".txt";
            input[i].open(small_file);
            if(!input[i])
            {
                cerr << "Can not read file!" << endl;
                exit(2);
            }
        }
        for(int i=0; i<10; ++i) //将每个小文件读入内存,排序,存储
        {
            string line;
            vector<unsigned int> nums;
            while(getline(input[i], line))
            {
                istringstream iss(line);
                unsigned int ui;
                while(iss >> ui)
                    nums.push_back(ui);
            }
            std::sort(nums.begin(), nums.end()); //使用标准库函数进行排序
            for(auto n : nums)
                output << n << " ";
            output << endl;
        }
        output.close();
        for(int i=0; i<10; ++i)
            input[i].close();
    }
private:
    string filename;
};

int main()
{
    /**1:生成大数据,当然这里只是模拟大数据,假设large_data.txt很大,无法一次读入内存,并且需要对其进行排序。*/
    large_data_generater ldg;
    ldg.generate();

    /**2:通过hash的方法对大文件进行分割,并且保证hash到每个小文件的数据属于同一个区间,这里也只是进行模拟。*/
    sort_large_data sld;
    sld.hash();

    /**3:对分割好的小文件进行排序,每个小文件是可以读到内存的。*/
    sld.sort();

    return 0;
}
这个应该是对大数据进行排序最naive的方法了,之后争取把bitmap、外排序的一些方法都尝试一下!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值