【问题标题】:Sorting a text file which contains integers, sorting has to be done line by line对包含整数的文本文件进行排序,必须逐行进行排序
【发布时间】:2019-09-25 13:20:47
【问题描述】:

我想对包含整数的文件进行排序,但只想逐行排序。我试过了,但我确定我在下面做的不是到位。

void sort_file_in_place(const char* filename) {
    fstream sort_file;
    sort_file.open(filename, ios::out | ios::in);
    vector <vector <int> > input_vect;
    string line;
    std::string delimiter = " ";
    int vect_index = 0;
    while (getline(cin, line)) {
        //store into vector of vectors
        //tokenise string 
        size_t pos = 0;
        int value = 0;
        int count = 0;
        while ((pos = line.find(delimiter)) != std::string::npos) {
            string token = line.substr(0, pos);
            line.erase(0, pos + delimiter.length());
            value = std::atoi(token.c_str());
            count++;
        }
        input_vect.resize(vect_index++, vector<int>(count));
    }
    //sort vector of vectors
    for (int i = 0; i < input_vect.size(); i++) {
        sort(input_vect[i].begin(), input_vect[i].end(), std::less<int>());
        //print the sorted vectors and alos verify the content 
        for (auto v : input_vect[i]) cout << v << " ";
    }
    //write back into the file
    //Todo
}

上面的代码不完整,但我希望你能得到我想问的。

请提出更好的解决方案。

我还想使用不同的线程对这些行进行排序,例如:

如果文件内容是:

13 38 13 100 4 234 85 34 0 100 88

1 4 5 3 8 9 1 10

111 10 112 3 4 098 194

5 4 8 3 9 13 24 78 09 99

我想创建四个线程来对每一行进行就地排序。

【问题讨论】:

  • 请只问一个问题。现在有多个:“如何在文件中逐行排序整数?”和“我如何在另一个线程上运行算法?”,(还有争议的第三个:“我如何将算法的工作分配给四个线程?”)
  • 我应该编辑这个问题吗?
  • 管理线程有开销。截至 2019 年,我预计线程所需的原始值 (integers) 的数量将有助于达到数千个。
  • 您正在使用就地工作的 std::sort 。您的代码看起来不错,您有什么改进意见?
  • @Amaresh 你不能避免缓冲区,你不能'直接在文本文件中'排序。

标签: c++ algorithm file sorting concurrency


【解决方案1】:

我看不到如何做到这一点“就地”。也许通过一些黑魔法,我们可以对元素进行排序,而无需将它们存储在内存中,但我对这种神秘科学一无所知:)

开个玩笑,如果将行存储到std::vector 中不适合您的需要,您可以使用您可能需要的任何其他容器,甚至是原始数组或自定义数组。但无论如何,您必须将这些行存储在某个地方来处理它们(在这种情况下对它们进行排序)。


我已经写了一个例子来实现你想要的:

#include <vector>
#include <fstream>
#include <algorithm>
#include <thread>

std::vector<std::string> split(const std::string & s, char c)
{
    std::vector<std::string> splitted;

    std::string word;
    for(char ch : s)
    {
        if((ch == c) && (!word.empty()))
        {
            splitted.push_back(word);
            word.clear();
        }
        else
            word += ch;
    }
    if(!word.empty())
        splitted.push_back(word);

    return splitted;
}
bool read_data(const std::string & file_path, std::vector<std::vector<int>> & data)
{
    data.clear();

    std::ifstream in_s(file_path);
    if(!in_s)
        return false;

    std::string line;
    std::vector <int> row;
    while(std::getline(in_s, line))
    {
        if(!line.empty())
        {
            for(auto s : split(line, ' '))
                row.push_back(std::stoi(s));
            data.push_back(row);
            row.clear();
        }
    }

    in_s.close();
    return true;
}
bool write_data(const std::string & file_path, const std::vector<std::vector<int>> & data)
{
    std::ofstream out_s(file_path);
    if(!out_s)
        return false;

    for(const auto & row : data)
    {
        for(size_t i = 0; i < row.size(); ++i)
        {
            if(i == 0)
                out_s << row[i];
            else
            {
                out_s << ((row[i] < 0) ? (" ") : ("  ")) << row[i];
            }
        }
        out_s << std::endl;
    }

    out_s.close();
    return true;
}
void sort_line(std::vector<int> & line)
{
    std::sort(line.begin(), line.end(), [](const int & i, const int & j){return i<j;});
}
void sort_data_lines(std::vector<std::vector<int>> & data)
{
    std::vector<std::thread> thread_mem;

    for(auto & row : data)
    {
        thread_mem.push_back(std::thread(sort_line, std::ref(row)));
    }

    for(auto & t : thread_mem)
        t.join();
}

我将代码分成三个主要功能,read_data() 用于从文件中读取数据,sort_data_lines() 用于对数据进行排序,write_data() 用于将数据写入文件。

可以这样使用:

int main()
{
    const std::string in_file_path("path/to/the/input_file.txt");
    const std::string out_file_path("path/to/the/output_file.txt");

    std::vector<std::vector<int>> data;
    if(!read_data(in_file_path, data))   // Read the data
        return -1;

    sort_data_lines(data);               // Sort the data

    if(!write_data(out_file_path, data)) // Write the sorted data
        return -2;

    return 0;
}

我对每一行进行了多线程排序(如所要求的那样),但我认为重要的是要注意,如果您的文件包含很多行(因此,很多同时运行线程)。
通常,将限制固定在 4 到 8 个运行线程之间是一个不错的选择。
当然,如果你的文件应该只包含四行,那没有问题,因为你只有 4 个正在运行的线程 :)


我使用以下输入文件进行了测试:

5  2  4  3  1 -3  8 -4 -1  0  1  0  6
6  9  3  1  5  2  6  8 -7 -1  0  0 -3
2  7  9  3  4  5 -5  6 -1  0  2 -2  3
0 -6 -2  8  5 -1  4  5 -6  7  2  2  0

我得到了以下输出文件:

-4 -3 -1  0  0  1  1  2  3  4  5  6  8
-7 -3 -1  0  0  1  2  3  5  6  6  8  9
-5 -2 -1  0  2  2  3  3  4  5  6  7  9
-6 -6 -2 -1  0  0  2  2  4  5  5  7  8

希望对你有所帮助。

【讨论】:

    猜你喜欢
    • 2019-09-30
    • 2017-05-05
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2016-03-17
    • 1970-01-01
    相关资源
    最近更新 更多