libStatGen Software
1
|
00001 /* 00002 * Copyright (C) 2010 Regents of the University of Michigan 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef _INPLACE_MERGE_H 00019 #define _INPLACE_MERGE_H 00020 00021 #include <algorithm> 00022 #if defined(DEBUG_INPLACE_MERGE) 00023 #include "Generic.h" 00024 #include <iostream> 00025 #endif 00026 #include <stdexcept> 00027 #include <vector> 00028 00029 00030 00031 // 00032 // given a partially ordered vector of values, use 00033 // inplace_merge to merge the ordered subsets together in some 00034 // reasonable fashion. 00035 // 00036 // On output, values is sorted in ascending order. 00037 // 00038 // the counts vector is also modified, the result being 00039 // undefined, except that counts[0] == values.size() at final exit. 00040 // 00041 template<typename T> void inplace_merge( 00042 std::vector<int> &indeces, 00043 std::vector<int> &counts, 00044 int first, 00045 int last, 00046 std::vector<T> &values) 00047 { 00048 if (first == (last)) return; // empty set -> no merge 00049 if (first == (last-1)) return; // only one set present -> no merge 00050 00051 // here we see if we have non-adjacent sets to merge, 00052 // if so, do them independently, then we can do a final 00053 // merge next 00054 if (first != (last - 2)) 00055 { 00056 int middle = (first + last) / 2; 00057 inplace_merge(indeces, counts, middle, last, values); 00058 #if defined(DEBUG_INPLACE_MERGE) 00059 std::cout << values; 00060 #endif 00061 inplace_merge(indeces, counts, first, middle, values); 00062 #if defined(DEBUG_INPLACE_MERGE) 00063 std::cout << values; 00064 #endif 00065 00066 // get ready to drop through to below code which will 00067 // merge our two merged subsets 00068 last = middle + 1; 00069 } 00070 00071 // inplace_merge just two adjacent sets 00072 typename std::vector<T>::iterator startIterator = values.begin()+indeces[first]; 00073 typename std::vector<T>::iterator middleIterator = values.begin() + indeces[last-1]; 00074 typename std::vector<T>::iterator endIterator = values.begin() + indeces[last-1] + counts[last - 1]; 00075 std::inplace_merge(startIterator, middleIterator, endIterator); 00076 counts[first] += counts[last - 1]; 00077 #if defined(DEBUG_INPLACE_MERGE) 00078 std::cout << values; 00079 #endif 00080 00081 return; 00082 } 00083 00084 #endif