libStatGen Software  1
InplaceMerge.h
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends