merge sort && loser tree

#ifndef __LoserTree__H #define __LoserTree__H #include <iostream> #include <fstream> #include <vector> #include <iterator> #include <algorithm> using namespace std; /* * V, 数据类 * P, 数据大小判定类,用于数据对象的比较与排序 * F, File Stream类,如SortedFile, UnSortedFile类,可以不停的从流中抽取数据对象(get_next函数);流中数据必须有序 * usage: * //归并a,b,c,d,e,f中的数据, 数据格式是每行一个整数,文件本身有序 * string file_name[6]={"a.txt","b.txt","c.txt","d.txt","e.txt","f.txt"}; * MultiMerge<int, less<int>, SortedFile<int, less<int> > > test(file_name, 6, less<int>(), max_int, min_int, "output.txt"); * test.Merge(); * * 无序文件通过传入UnSortedFile,该对象会先将文件内排序 * * 必需指定数据的上下界,使得文件中的数据都在界内;否则程序会出异常。 * * Merge函数可以控制是否对相同key的数据进行合并; (实现中, 在归并败者树创建阶段不合并,在最后输出阶段合并) * * 当使用自定义的V时, 需要提供对应的 F.operator(), fstream的operator >> & <<; * 当指定归并相同key的数据时, 需要提供归并的函数. 第一个参数是in|out类型参数, 注意函数原型 */ //处理文件内本身有序的数据 template <class V, class P> class SortedFile { public: SortedFile(const string &path, P f, const string & fp):m_fin(path.c_str()){} bool get_next(V & e) { if(m_fin >> e) return true; return false; } ~SortedFile() { m_fin.close(); } private: ifstream m_fin; }; //处理文件内本身无序的数据。 会读取文件,在内存中排好序,然后输出到同名文件 template <class V, class P> class UnSortedFile { public: UnSortedFile(const string &path, P f, const string & fp) { this->sort(path, f, fp); m_fin.open(path.c_str()); } bool get_next(V & e) { if(m_fin >> e) return true; return false; } ~UnSortedFile() {m_fin.close();} private: void sort(const string & path, P &f, const string & fp) { vector<V> allvalues; V value; ifstream fin(path.c_str()); while(fin >> value) { allvalues.push_back(value); } fin.close(); std::sort(allvalues.begin(), allvalues.end(), f); ofstream fout(path.c_str(), ios::out); copy(allvalues.begin(), allvalues.end(), ostream_iterator<V>(fout, fp.c_str())); fout.close(); } private: ifstream m_fin; }; // 多路归并排序。 template <class V, class P, class F> class MultiMerge { public: MultiMerge(const string filename[], unsigned int num, P f, const V &mx, const V &mn, const string & fp, const string &output); void Merge(bool merge_same_key = false, V &(*func)(V &, const V &) = 0); //true时,对相同key进行合并; false时不合并。 相同通过 F.operator(l, r) == false && F.operator(r, l) == false ~MultiMerge(); private: typedef vector<int> LoserTree; // 败者树。 存放叶子节点的索引 typedef vector<V> Leaf; // 叶子。 unsigned int m_filenum; // 实际文件数。 P m_f; // 用于比较的函数对象 F ** m_file; // 为每个文件建立ReadFile对象。 string m_outfile; // 归并后生成文件名。 void create_losertree(LoserTree &tree, Leaf &leaf); // 建败者树,具体介绍请看严蔚敏《数据结构》P-298 void adjust(LoserTree &tree, Leaf &leaf, int s); V m_max; // m_max,排序中某文件到达文件尾则使用此值 V m_min; // m_min,构造败者树时初始树结点,以便比较找出败者 string m_fs; // 文件中数据记录的分隔符 }; template <class V, class P, class F> MultiMerge<V, P, F>::MultiMerge(const string filename[], unsigned int num, P f, const V &mx, const V &mn, const string & fp, const string &name): m_filenum(num), m_f(f), m_outfile(name), m_max(mx), m_min(mn), m_fs(fp) { m_file = new F *[m_filenum]; for(unsigned int i = 0; i < m_filenum; i++) { m_file[i] = new F(filename[i], m_f, m_fs); } } template <class V, class P, class F> void MultiMerge<V, P, F>::adjust(LoserTree &tree, Leaf &leaf, int s) { int parent = (s + m_filenum) / 2; while(parent > 0) { if(m_f.operator()(leaf[tree[parent]], leaf[s])) { int temp = s; s = tree[parent]; tree[parent] = temp; } parent = parent / 2; } tree[0] = s; } template <class V, class P, class F> void MultiMerge<V, P, F>::create_losertree(LoserTree &tree, Leaf &leaf) { leaf[m_filenum] = m_min; for(unsigned int i = 0; i < m_filenum; i++) tree[i] = m_filenum; for(int j = m_filenum - 1; j >= 0; j--) adjust(tree, leaf, j); } template <class V, class P, class F> void MultiMerge<V, P, F>::Merge(bool merge, V &(*func)(V &, const V &)) { LoserTree tree(m_filenum); Leaf leaf(m_filenum + 1); tree.assign(m_filenum, 0); leaf.assign(m_filenum + 1, V()); int min; ofstream fout(m_outfile.c_str(), ios_base::out); for(unsigned int i = 0; i < m_filenum; i++) { if(!m_file[i]->get_next(leaf[i])) { leaf[i] = m_max; } } create_losertree(tree,leaf); //for merge same key V pre = m_min; //dummy value bool first = true; while(m_f.operator()(leaf[tree[0]], m_max)) { min = tree[0]; if(merge && func) { if(!m_f.operator()(pre, leaf[min])) //equal; because pre <= leaf[min] func(pre, leaf[min]); else { if(!first) fout << pre << m_fs; //output pre record else { first = false; //skip dummy value } pre = leaf[min]; } } else { fout << leaf[min] << m_fs; } if(!m_file[min]->get_next(leaf[min])) { leaf[min] = m_max; } adjust(tree, leaf, min); } if(merge && func) { fout << pre << m_fs; } fout.close(); } template <class V, class P, class F> MultiMerge<V, P, F>::~MultiMerge() { if(m_file) { for(unsigned int i = 0; i < m_filenum; i++) delete m_file[i]; delete [] m_file; } } #endif

 

 

//example call code

MultiMerge<int, less<int>, UnSortedFile<int, less<int> > > test(file_name, 6, less<int>(), 100, -100, "/n", build_name[2]);test.Merge();

你可能感兴趣的:(String,tree,File,Class,FP,merge)