현재 C++ 프로젝트에는 정수 키를 객체에 매핑하는 STL 맵이 있습니다. 알고리즘은 일련의 항목을 반환합니다. 반환 된 데이터는 알고리즘의 입력에 따라 달라집니다 때문에 예측할 수 없습니다 :C++ STL : iterator와 reverse_iterator에 기본 클래스가 누락되어 중복 코드가 발생했습니다.
class MyClass
{
//...
};
int myAlgorithm(vector<int>::iterator inputIt)
{
// return a key for myMap which is calculated by the current value of inputData
}
int main(int argc, char *argv[])
{
vector<int> inputData;
map<int, MyClass> myMap;
//<fill map with some data>
//<fill inputData>
vector<MyClass> result;
for (vector<int>::iterator it = inputData.begin(); it != inputData.end(); it++)
{
int myMapKey = myAlgorithm(*it);
// count() > 0 means "check whether element exists. Performance can be improved by replacing
// the operator[] and count() calls by map::find(). However, I want to simplify things
// in this example.
if (myMap.count(myMapKey) > 0)
{
// in some cases there is no entry in myMap
result.push_back(myMap[myMapKey]);
}
}
}
내가 발견과 map::count()
및 operator[]
-calls를 대체 할 수있는 예에서 언급 한 바와 같이. STL-reference은 map :: find()의 복잡성이 로그의 크기가 (O(log n)
)라고 말합니다.
대부분의 경우 myMap의 항목이 결과에서 두 개의 연속 항목에 매우 가깝다는 것을 발견했습니다. 그러므로 나는 내가 map.find을 (교체하면 더 나은 성능을 달성 할 결론)에 와서는 반복자에 의해 호출
map<int, MyClass>::iterator myMapIt = myMap.begin();
for (vector<int>::iterator it = inputData.begin(); it != inputData.end(); it++)
{
int myMapKey = myAlgorithm(*it);
// just increment iterator
while (myMapKey != myMapIt->first)
{
myMapIt++;
// we didn't find anything for the current input data
if (myMapIt == myMap::end() || myMapIt->first > myMapKey)
{
break;
}
}
// I know that I'm checking this twice, but that's not the point of my
// question ;)
if (myMapIt == myMap::end() || myMapIt->first > myMapKey)
{
// probably it would be better to move the iterator back to the position
// where we started searching, to improve performance for the next entry
myMapIt = myMap.begin();
}
else
{
result.push_back(myMapIt.second);
}
}
이 개념 작동하지만 난 큰 문제가 다음 inputData에 따라, 내가해야 앞으로 또는 뒤로 검색. main()
안에 코드를 여러 번 호출하고 이러한 호출에 대해 inputData가 변경되었다고 간주하십시오. while
-loop 내부의 반복기를 증가 또는 감소 시킬지 여부를 확인하는 대신 for
-loop을 입력하기 전에이를 결정할 수있었습니다.
map<>::reverse_iterator
에
map<>::iterator
전환 및
rbegin()
/
rend()
대신
begin()
/
end()
을 사용하여 괜찮아 생각했다. 그러나 나는
reverse_iterator
과
iterator
가 공통 기본 클래스가 없다는 것을 깨달았다
map<int, MyClass>::base_iterator myIt;
if (/* ... */)
{
myMapIt = myMap::begin();
myMapEndIt = myMap::end();
}
else
{
myMapIt = myMap::rbegin();
myMapEndIt = myMap::rend();
}
/* for (...) ... */
좋은 것입니다,하지만 base_iterator
이 없습니다.
for
-loop를 복사하여 조정해야합니다
if (/* ... */)
{
/* for(...) which uses normal iterator in the while-loop */
}
else
{
/* for(...) which uses reverse iterator in the while-loop */
}
는 아주 나쁜 ... 당신이 더 나은 솔루션을 알고 있습니까?
함수 템플릿을 호출하면 작동합니까? – PlasmaHH
더 나은 성과를 달성한다는 결론에 어떻게 도달 했습니까? 백업 할 데이터가 있습니까? 응용 프로그램에서 이것이 실제 병목 현상이 아니라면 직접 더 많은 작업을 할 수 있습니다. 즉, 여전히 흥미로운 질문입니다. :) – Scott
'map :: find()'를 사용할 때 O (log n) 복잡성으로 인해 다음 항목이 현재 항목에 가깝다고 가정 할 수 없기 때문에 복잡합니다. 이 코드는 몇 개의 중첩 루프 내부에서 매우 중요한 위치에 있습니다. – fishbone