// Copyright (c) // All rights reserved. // //Describe : Premutation And Combination generater //Author : Qing //Date : 2015-01-19 #ifndef __PREMUTATION_COMBINATION_H__ #define __PREMUTATION_COMBINATION_H__ #include <bitset> #include <vector> #include <algorithm> namespace Qing { template<typename T, unsigned int ElementCount> class PermutationCombination { public: PermutationCombination(void) {} ~PermutationCombination(void){} bool GetCombination(const std::vector<T> &SourceVector, int CombinationElementCount, std::vector<std::vector<T> > &ResultVector); bool GetPermutation(const std::vector<T> &SourceVector, int PermutationElementCount, std::vector<std::vector<T> > &ResultVector); private: bool AdjustPosition(std::bitset<ElementCount> &FlagArray, unsigned int SourceVectorElementCount); }; template<typename T, unsigned int ElementCount> bool PermutationCombination<T,ElementCount>::GetCombination(const std::vector<T> &SourceVector, int CombinationElementCount, std::vector<std::vector<T> >& ResultVector) { if(SourceVector.size() <= 0 || CombinationElementCount <= 0 || CombinationElementCount > static_cast<int>(SourceVector.size())) { return false; } std::bitset<ElementCount> FlagArray; for(int Index = 0; Index < CombinationElementCount; Index++) { FlagArray.set(Index); } do { ResultVector.push_back(std::vector<T>(CombinationElementCount, T())); std::vector<T> &TempArray = ResultVector[ResultVector.size()-1]; std::vector<T>::size_type TempIndex = 0; for(std::size_t BitSetIndex = 0; BitSetIndex < FlagArray.size(); BitSetIndex++) { if(FlagArray[BitSetIndex]) { TempArray[TempIndex] = SourceVector[BitSetIndex]; if(++TempIndex == CombinationElementCount) { break; } } } } while(AdjustPosition(FlagArray, SourceVector.size())); return true; } template<typename T, unsigned int ElementCount> bool PermutationCombination<T,ElementCount>::GetPermutation(const std::vector<T> &SourceVector, int PermutationElementCount, std::vector<std::vector<T> >& ResultVector) { if(SourceVector.size() <= 0 || PermutationElementCount <= 0 || PermutationElementCount > static_cast<int>(SourceVector.size())) { return false; } std::bitset<ElementCount> FlagArray; for(int Index = 0; Index < PermutationElementCount; Index++) { FlagArray.set(Index); } std::vector<T> TempArray(PermutationElementCount,T()); do { std::vector<T>::size_type TempIndex = 0; for(std::size_t BitSetIndex = 0; BitSetIndex < FlagArray.size(); BitSetIndex++) { if(FlagArray[BitSetIndex]) { TempArray[TempIndex] = SourceVector[BitSetIndex]; if(++TempIndex == PermutationElementCount) { do { ResultVector.push_back(TempArray); } while (next_permutation(TempArray.begin(), TempArray.end())); break; } } } } while(AdjustPosition(FlagArray, SourceVector.size())); return true; } //*********************** 0-1 exchange algorithm ************************ // example : C(5,3) // 1 1 1 0 0 // 1 1 0 1 0 // 1 0 1 1 0 // 0 1 1 1 0 // 1 1 0 0 1 // 1 0 1 0 1 // 0 1 1 0 1 // 1 0 0 1 1 // 0 1 0 1 1 // 0 0 1 1 1 //*********************** 0-1 exchange algorithm ************************ template<typename T, unsigned int ElementCount> bool PermutationCombination<T,ElementCount>::AdjustPosition(std::bitset<ElementCount> &FlagArray, unsigned int SourceVectorElementCount) { SourceVectorElementCount -= 1; for(unsigned int i = 0; i < SourceVectorElementCount; i++) { if(FlagArray[i] && !FlagArray[i+1]) { FlagArray.reset(i); FlagArray.set(i + 1); if(!FlagArray[0] && i != 0) { int TrueCount = 0; for(unsigned int j = 0; j < i; j++) { if(FlagArray[j]) { ++TrueCount; } FlagArray.reset(j); } for(int k = 0; k < TrueCount; k++) { FlagArray.set(k); } } return true; } } return false; } } #endif