简体   繁体   中英

C++ - Alternative to iterating vector

I have a std::vector<MyClass*> (a vector of MyClass pointers), and I need to find a particular item in the vector. The class has a getID() function which returns a unique identifier of the class.

If I want to find a class with a specific ID, I iterate through the vector looking for the class with the ID, like this:

for(std::vector<Chunk*>::iterator it = chunksRenderList.begin(); it != chunksRenderList.end(); ++it)
{
    if((*it)->getID() == id)
        return *it;
}

This is rather slow because I am calling this code lots of times per second. I have tried using a std::unordered_map which was a lot slower, and a std::map was slower again. I'm not sure why it was slower, maybe it's the way I used it.

Is there any container/algorithm I can use to access a particular item without having to iterate (that is faster than iteration)?

If your container is sorted accoding to the value of getID() you may try using a binary search.

class A
{
  size_t m_id;
public:
  A (size_t id) : m_id(id) {}
  size_t getID (void) const { return m_id; }
};

template<class T1, class T2>
struct less_id
{
  bool operator () (T1 const &lhs, T2 const & cmp)
  {
    return (lhs->getID() < cmp);
  }
};

int main (void)
{
  std::vector<A*> v;
  v.push_back(new A(2));
  v.push_back(new A(3));
  v.push_back(new A(4));
  v.push_back(new A(5));

  less_id<A*, size_t> cmp;

  size_t find_value = 4;
  std::vector<A*>::iterator found = std::lower_bound(v.begin(), v.end(), find_value, cmp);
  if(found == v.end() || !((*found)->getID() == find_value))
  {
    // not found
  }
  else
  {
    // found
    std::cout << "Found element: " << (found-v.begin()) << std::endl;
  }

  for (size_t i=0; i<v.size(); ++i) delete v[i];
  v.clear();
}

Shows

Found element: 2

Where A == Chunk and v == chunksRenderList .

If you're doing this enough to justify it, the obvious thing to do would be to sort the vector, then use a binary search to find your item.

If your ID's are reasonably predictably distributed over the range they cover, you could use an interpolating search to reduce the complexity from O(N) to roughly O(log log N) -- though it has enough higher constant that it's generally only a win with a fairly large collection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM