有时候很多基于文件的外部排序算法都需要合并两个有序的文件。下面就给出简单的C++实现方法。具体思路和合并两个有序的单链表的思路是一样的。
void merge_file(const string& file_in_name1,const string& file_in_name2,const string& file_out_name) { //打开两个输入文件和一个输出文件 ifstream fin1,fin2; fin1.open(file_in_name1.c_str(),ios::in | ios::binary); fin2.open(file_in_name2.c_str(),ios::in | ios::binary); ofstream fout; fout.open(file_out_name.c_str(),ios::out | ios::binary); //在每个文件中先各读出第一个数 int temp1,temp2; fin1.read(reinterpret_cast<char*>(&temp1),sizeof(int)); fin2.read(reinterpret_cast<char*>(&temp2),sizeof(int)); //在两个文件中前进,每次只选择两个文件中较小的那个数添加到输出文件的末尾 while (true) { if (temp1<=temp2) { fout.write(reinterpret_cast<const char*>(&temp1),sizeof(int)); //到文件的最后一个数读完之后,再读一次,保证每个文件中的所有数据都被读到。 fin1.read(reinterpret_cast<char*>(&temp1),sizeof(int)); if (fin1.eof()) { break; } } else { fout.write(reinterpret_cast<const char*>(&temp2),sizeof(int)); fin2.read(reinterpret_cast<char*>(&temp2),sizeof(int)); if (fin2.eof()) { break; } } } if (!fin1.eof()) { while (true) { //另一个文件已经读完了,说明当前这个文件中最后读到的那个整数还没有被写出,所以要先写出。 fout.write(reinterpret_cast<const char*>(&temp1),sizeof(int)); fin1.read(reinterpret_cast<char*>(&temp1),sizeof(int)); if (fin1.eof()) { break;; } } } else while (true) { fout.write(reinterpret_cast<const char*>(&temp2),sizeof(int)); fin2.read(reinterpret_cast<char*>(&temp2),sizeof(int)); if (fin2.eof()) { break; } } fin1.close(); fin2.close(); fout.close(); }
int main( void ) { vector<int> a; push_rand(a); sort(a.begin(),a.end()); write_data_to_file(a,"data1.txt"); print_file("data1.txt"); a.clear(); push_order(a,100); write_data_to_file(a,"data2.txt"); print_file("data2.txt"); merge_file("data1.txt","data2.txt","data.txt"); print_file("data.txt"); return 0; }
main函数中用到了例如push_rand这样的函数,都是自己为了测试而写的,不是很重要。可以比较方便的实现,就不一一列出了。这个函数可以用于二路归并排序文件。K路归并的算法要做一些记录性的处理。在后面的博客中给出。