结合STL采用排序+回溯. 目前支持windows平台, 但可稍作修改移植到Linux.
- /********************************************************************
- created: 2008/11/09
- created: 9:11:2008 16:07
- filename: CConditionCombination.h
- file path:
- file base: CConditionCombination
- file ext: h
- author: rawman
- email: rawman_9527@sina.com
- purpose: This module is designed to calculate a kind of condit-
- ionally mathematic combination, in which each result
- group's key sum equals(or mostly equals) to the condi-
- tional value given.
- attention: The following parameter KEYTYPE can be integer , sin-
- gle or double data type, don't forget to set the Comp-
- arePrecision if KEYTYPE is float or double, the Compa-
- rePrecision should not be minus, besides that you can
- also set the ComparePrecision to get the region group-
- s if KEYTYPE is integer
- *********************************************************************/
- #ifndef __CCONDITIONCOMBINATION_H__
- #define __CCONDITIONCOMBINATION_H__
- #include <Windows.h>
- #include <map>
- #include <vector>
- namespace ConditionCombination
- {
- template<typename KEYTYPE, typename DATATYPE>
- class CConditionCombination
- {
- public:
- CConditionCombination(std::multimap<KEYTYPE, DATATYPE>& DataMap, KEYTYPE ConditionValue);
- CConditionCombination(KEYTYPE ConditionValue);
- public:
- // the following functions just operate an element in the DataSource
- bool InsertAnElement(IN KEYTYPE Key, IN const DATATYPE& Data);
- bool RemoveAnElement(IN KEYTYPE Key);
- bool ModifyAnElement(IN KEYTYPE Key, IN const DATATYPE& Data);
- // to calculate the result
- void Make(OUT std::vector<std::multimap<KEYTYPE, DATATYPE> >& Result);
- // to set ComparePrecision
- void SetCmpPrecision(IN KEYTYPE ComparePrecision);
- private:
- std::multimap<KEYTYPE, DATATYPE> m_mmapData; // DataSource
- KEYTYPE m_ktConditionValue; // conditional value
- KEYTYPE m_ktCmpPrecision; // ComparePrecision
- };
- template<typename KEYTYPE, typename DATATYPE>
- CConditionCombination<KEYTYPE, DATATYPE>::CConditionCombination(std::multimap<KEYTYPE, DATATYPE>& DataMap, KEYTYPE ConditionValue)
- : m_mmapData(DataMap)
- , m_ktConditionValue(ConditionValue)
- , m_ktCmpPrecision(0)
- {
- }
- template<typename KEYTYPE, typename DATATYPE>
- CConditionCombination<KEYTYPE, DATATYPE>::CConditionCombination(KEYTYPE ConditionValue)
- : m_ktConditionValue(ConditionValue)
- , m_ktCmpPrecision(0)
- {
- }
- template<typename KEYTYPE, typename DATATYPE>
- bool CConditionCombination<KEYTYPE, DATATYPE>::InsertAnElement(IN KEYTYPE Key, IN const DATATYPE& Data)
- {
- std::pair<std::multimap<KEYTYPE, DATATYPE>::iterator, bool> pairRet;
- pairRet = m_mmapData.insert(std::make_pair(Key, Data));
- return pairRet.second;
- }
- template<typename KEYTYPE, typename DATATYPE>
- bool CConditionCombination<KEYTYPE, DATATYPE>::RemoveAnElement(IN KEYTYPE Key)
- {
- std::multimap<KEYTYPE, DATATYPE>::iterator iter;
- iter = m_mmapData.find(Key);
- if(iter == m_mmapData.end())
- {
- return false;
- }
- m_mmapData.erase(iter);
- return true;
- }
- template<typename KEYTYPE, typename DATATYPE>
- bool CConditionCombination<KEYTYPE, DATATYPE>::ModifyAnElement(IN KEYTYPE Key, IN const DATATYPE& Data)
- {
- std::multimap<KEYTYPE, DATATYPE>::iterator iter;
- iter = m_mmapData.find(Key);
- if(iter == m_mmapData.end())
- {
- return false;
- }
- iter->second = Data;
- return true;
- }
- template<typename KEYTYPE, typename DATATYPE>
- void CConditionCombination<KEYTYPE, DATATYPE>::Make(OUT std::vector<std::multimap<KEYTYPE, DATATYPE> >& Result)
- {
- KEYTYPE Sum = 0; // to use in calculating key sum
- std::multimap<KEYTYPE, DATATYPE>::iterator iter = m_mmapData.begin();
- std::vector<std::multimap<KEYTYPE, DATATYPE>::iterator> vecAGroupPtr; // to use in geting a respected group
- while(true)
- {
- // the iterator has moved to the last,
- // it cannot move forward any more and must to check whether it can trace back to the last step
- while(iter == m_mmapData.end())
- {
- if(vecAGroupPtr.size() == 0) // no steps can be traced to
- {
- return;
- }
- // trace back to the last step
- iter = vecAGroupPtr[vecAGroupPtr.size() - 1];
- Sum -= iter->first;
- vecAGroupPtr.pop_back();
- iter++;
- }
- if(Sum + iter->first + m_ktCmpPrecision < m_ktConditionValue) // if has no cmpprecision, it should be: Sum + iter->first < m_ktConditionValue
- {
- vecAGroupPtr.push_back(iter);
- Sum += iter->first;
- }
- else if( (Sum + iter->first - m_ktCmpPrecision <= m_ktConditionValue)
- && (Sum + iter->first + m_ktCmpPrecision >= m_ktConditionValue) )
- // if has no cmpprecision, it should be: Sum + iter->first == m_ktConditionValue
- {
- std::multimap<KEYTYPE, DATATYPE> mmapAGroup;
- for(size_t i = 0; i < vecAGroupPtr.size(); i++)
- {
- mmapAGroup.insert(std::make_pair(vecAGroupPtr[i]->first, vecAGroupPtr[i]->second));
- }
- mmapAGroup.insert(std::make_pair(iter->first, iter->second));
- Result.push_back(mmapAGroup);
- }
- else // if has no cmpprecision, here means: Sum + iter->first > m_ktConditionValue
- {
- if(vecAGroupPtr.size() > 0)
- {
- Sum -= vecAGroupPtr[vecAGroupPtr.size() - 1]->first;
- iter = vecAGroupPtr[vecAGroupPtr.size() - 1];
- vecAGroupPtr.pop_back();
- }
- else // if has no cmpprecision, here means: Sum == 0 && iter->first > m_ktConditionValue
- // do not need to calculate any more because after the iterator (include) any element's key value has exceeded the conditional value within precision
- {
- break;
- }
- }
- iter++;
- } // while(true)
- }
- template<typename KEYTYPE, typename DATATYPE>
- void CConditionCombination<KEYTYPE, DATATYPE>::SetCmpPrecision(IN KEYTYPE ComparePrecision)
- {
- m_ktCmpPrecision = ComparePrecision;
- }
- } // namespace ConditionCombination
- #endif
该模型的使用演示:
- #include "CConditionCombination.h"
- #include <iostream>
- #include <string>
- using namespace ConditionCombination;
- void Display(std::vector<std::multimap<int, std::string> >& Result)
- {
- for(size_t i = 0; i < Result.size(); i++)
- {
- for(std::multimap<int, std::string>::iterator iter = Result[i].begin();
- iter != Result[i].end(); iter++)
- {
- std::cout<<"("<<iter->first<<","<<iter->second<<")"<<" ";
- }
- std::cout<<std::endl;
- }
- std::cout<<std::endl;
- }
- int main(int argc, char* argv[])
- {
- std::multimap<int, std::string> MyMap;
- MyMap.insert(std::make_pair(14, "String1"));
- MyMap.insert(std::make_pair(12, "String2"));
- MyMap.insert(std::make_pair(12, "String3"));
- MyMap.insert(std::make_pair(14, "String4"));
- MyMap.insert(std::make_pair(14, "String5"));
- MyMap.insert(std::make_pair(10, "String6"));
- MyMap.insert(std::make_pair(14, "String7"));
- MyMap.insert(std::make_pair(10, "String8"));
- MyMap.insert(std::make_pair(12, "String9"));
- MyMap.insert(std::make_pair(12, "String10"));
- MyMap.insert(std::make_pair(10, "String11"));
- MyMap.insert(std::make_pair(12, "String12"));
- MyMap.insert(std::make_pair(12, "String13"));
- MyMap.insert(std::make_pair(8, "String14"));
- MyMap.insert(std::make_pair(6, "String15"));
- MyMap.insert(std::make_pair(7, "String16"));
- MyMap.insert(std::make_pair(5, "String17"));
- MyMap.insert(std::make_pair(5, "String18"));
- MyMap.insert(std::make_pair(5, "String19"));
- MyMap.insert(std::make_pair(5, "String20"));
- MyMap.insert(std::make_pair(6, "String21"));
- // the following statement demonstrates how to use the CConditionCombination
- CConditionCombination<int, std::string> Test(MyMap, 35);
- Test.SetCmpPrecision(0); // you can also set the CmpPrecision 1 to try...
- std::vector<std::multimap<int, std::string> > Result;
- Test.Make(Result);
- Display(Result);
- std::cout<<"There are "<<Result.size()<<" groups"<<std::endl;
- getchar();
- // you can also set KEYTYPE float to try..., but don't forget to set CmpPrecision
- return 0;
- }