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-298void 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 keyV pre = m_min; //dummy valuebool 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 recordelse{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();
總結
以上是生活随笔為你收集整理的merge sort loser tree的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ifstream note
- 下一篇: sed 示例