[算法]“百万级”浮点数排序

1-百万数据[IO/sort/vector]

  • 排序问题三步:读文件、排序、写文件
    • 一.读文件
    • 二、读文件后检测容器大小和已知数据的匹配关系,设置数据精度
    • 三、排序(C++内置sort)
    • 四、写文件(※)

排序问题三步:读文件、排序、写文件

一.读文件

1.整体三秒版读文件[以行为单位的double数读入vector]

  • [应用了filebuf->sgetn、ifstream.rdbuf()、istringstream、vector.reserve]
  • 通过istringstream对已获取文件信息的string input作进一步操作,以换行为分隔符将每个substr用stof转换为double数后push_back入vector
//读入txt,一百万行,每行一个double数,数据存入vector
//下面重写buffer 加载char*
    ifstream filestr;
    long size;
    char * buffer;
    filebuf *pbuf;

    filestr.open ("M1.txt", ios::binary);//二进制方式打开文件

    pbuf = filestr.rdbuf();//利用filebuf *pbuf对ifstream输入流内容重定向

    size=pbuf->pubseekoff (0,ios::end,ios::in);//获取文件字节大小,1字节==sizeof(char)

    pbuf->pubseekpos (0,ios::in);//将指针位置更改为文件初始位置

    buffer=new char[size];//预先为字符串分配与文件大小相同的缓冲区

    pbuf->sgetn (buffer,size);//调用filebuf的sgetn()函数填充字符串缓冲区char *buffer
    filestr.close();//关闭ifstream

    string input(buffer);
    //cout<> fVecSim){
        //cout<>fVecSim;
        vec_similarity.push_back(atof(fVecSim.c_str()));
    }*/

2.有问题的快速读文件(第一版)[读入vector]

/*有问题的buffer和char*部分
    ifstream iVecSim("M3.txt");

    iVecSim.seekg(0,iVecSim.end);

    long long file_size = iVecSim.tellg();//大小

    iVecSim.seekg(0,iVecSim.beg);

    char *buffer = new char[file_size];
    iVecSim.read(buffer,file_size);
*/

3.来自性能优化指南的读文件方法——file_reader(),写入string,耗时0.4s

  • [应用了filebuf->sgetn、ifstream.rdbuf()、istringstream、vector.reserve]
  • 实际上这个方法是1的简化版
  • [有时间时候需要将这两种方法结合起来,尝试进一步优化]
  • [后经过检验,该方法并不如filebuf填充的效果好]
#include 
#include
#include
#include
#include
#include
using namespace std;
//void stream_read_streambuf_stringstream(std::istream& f, std::string& result);


//1 这个简单的方法就可以实现把所有的文件内容读取到一个string中 0.4 s
std::string file_reader(char const* fname){
    std::fstream f;
    f.open(fname);
    if(!f){
        std::cout<<"CAN NOT OPEN"<(f.rdbuf()),
              std::istreambuf_iterator(),
              std::ostreambuf_iterator(s));
    return s.str();
}

int main()
{
    //cout << "Hello world!" << endl;

    // 对1的调用
    //clock_t t1 = clock();
    std::string s;
    //std::ifstream f;

    s = file_reader("M1.txt");
    cout<<"OK"<

二、读文件后检测容器大小和已知数据的匹配关系,设置数据精度

    cout<::iterator it = vec_similarity.begin();it != vec_similarity.end();it++){
        cout<<*it<

三、排序(C++内置sort)

//对vector的内容进行排序
    sort(vec_similarity.begin(), vec_similarity.end());// 到这里一共1.5s 读入需要1.099s sort()需要大概0.5s
    cout<<"sort succeed"<

四、写文件(※)

1.开ofstream,直接将vector写入 | [改良]利用sprintf

//1-将排好序的vector的内容写入文件中
//直接写double,改为下标访问,总时间11s
//2019-2-8 12:48 将直接输出double数改为:通过sprintf将double转换为char[] ,速度提升了4倍,降低为原时间的25%

    std::ofstream res("res_directly.txt");
    res << std::setprecision(10);
    for(unsigned i=0; i

2.二进制输出

/*
    //2-该方法输出格式为二进制文件
    int k=0;
    for(vector::iterator it = vec_similarity.begin();it != vec_similarity.end();it++){
        da[k++] = *it;//这里对vector进行遍历不需要花多少时间 保存到了double数组da中[全局]
    }

    int len = sizeof(double) * vec_similarity.size();
    ofstream ofile;
    ofile.open("res4.txt",ios::binary);
    ofile.write((const char*)da, len);
    ofile.close();
*/

3.利用迭代器和std::copy进行格式化输出

/* 3-该方法1 精度不对  2时间太长 12s
    std::ofstream output_file("res.txt");
    std::ostream_iterator output_iterator(output_file,"\n");
    std::copy(vec_similarity.begin(), vec_similarity.end(), output_iterator);
*/

4.将vector元素转换为string | char* buffer指向的内容

-当将所有数据内容集中到一个string中,再一次性用ofstream 的 << 运算符,即可快速写入文件

/*//4-该方法虽然将vector中的内容全部转换为string添加到result中,但时间过长,共16s 还不如上一个方法;
  //或者改为char*数组,利用sprintf 和 strcat进行拼接,更慢
 //改成了下标访问,还是很慢

//想办法将vector中的内容全部保存到   char*

    long size2 = sizeof(double) * vec_similarity.size();
    char *buffer2 = new char[size2];

    for(unsigned i=0;i

你可能感兴趣的:(算法)