【问题标题】:Merge multiple txt files into one将多个txt文件合并为一个
【发布时间】:2015-07-09 14:53:07
【问题描述】:

下午好。

我遇到了一些问题。可以解决,但是我的编程经验很少,在我看来这个问题有更漂亮更合理的解决方案。

问题如下。给定一组总大小超过一百兆字节的文本文件。文件数从 2 到 N。文件包含排序后的唯一编号(例如 ID)。 它想将所有数字合并到一个输出文件中。里面生成的文件编号也需要排序。

我将按如下方式解决此问题: 打开所有文件。取出每个文件的第一个数字。将它们放入容器中(例如,载体)。找到容器中最小的数字。将最小的数字放在输出文件中。取而代之的是文件中的以下数字,从中取出最小的数字。 这个方法好像叫“外部归并排序”。

请告诉我,有没有更聪明的方法来解决这个问题?

【问题讨论】:

  • 取决于。期望的复杂度是多少?
  • @Let_Me_Be 很难说。我认为是初级水平。
  • 我的意思是计算复杂度:-D
  • @Let_Me_Be 对不起。迷失在翻译中。:) 我对此事没有严格的标准。所以,最好的。

标签: c++ file boost merge


【解决方案1】:

为这个确切的问题创建了外部合并排序。这种复杂度是N * log(number_of_files)

为简化代码,您可以将文件流与数字一起存储在优先级队列中。

完全未经测试,但可能有用的代码:

std::vector<ifstream> file_streams(stream_count);  
// open streams.
using int_and_stream = std::pair<int, std::ifstream&>;
using cont = std::vector<int_and_stream>;
std::priority_queue<int_and_stream, cont, pair_comparer> queue;

for(auto& stream: file_streams){
   int id;
   stream >> id;
   queue.push(std::make_pair(id, stream));
}

while(!queue.empty()){
   auto smallest = queue.top();
   outstream << smallest.first;
   int id;
   if(smallest.second >> id){ // file ended?
      queue.push(std::make_pair(id, stream));
   }
}              

对于pair_comparer,您可以查看here

【讨论】:

  • 似乎所有改进都归结为使用优先级队列。我想这就是我要做的。非常感谢大家。
  • @Captain Giraffe 没有什么困难。这里: queue.push(std::make_pair(id, stream));错误号 С2280。禁止 ifstream 的复制构造函数。我尝试使用 std::reference_wrapper,但没有成功。
  • @Merovingean 试试new int_and_stream(id, stream) 或提出新问题。
【解决方案2】:

你的方法很好。

但是你可以有一个数字/文件对的排序向量,所以你会花费更少的时间来寻找最小的数字,因为在取出最小的条目之后,你可以读取下一个值并使用更有效的算法将其插入数组中,而不是线性排序。当您有大量输入文件时,这会更有效。

但假设 I/O 的成本比数字比较贵得多,这种方法是可以的。

【讨论】:

  • 使用std::set&lt;std::pair&lt;FILE*, Number&gt;&gt; 是最简单的,其中Number 可以是整数类型或浮点类型,具体取决于数据。
【解决方案3】:

更好的方法是将每个文件的当前头存储在优先级队列中。然后,在每一步中,您都取优先级队列的顶部(注意该项目来自的输入文件),将其写入输出文件,并将该输入文件的下一项推送到优先级队列中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多