Looking for efficient algorithm on list iterator

Mar 6, 2013 at 4:51pm
Hi,

I have a list and a vector, for example like
1
2
list<int> mylist = {1, 1, 1, 0, 0, 1, 0, 0}
vector<int> myvec;

I want to create an efficient algorithm to erase all element of value "1", and give these elements to a vector. My code (not efficient) is as follows
1
2
3
4
5
6
7
8
for(auto it = mylist.begin(); it != mylist.end(); it++) {
   if(*it == 1) {
      myvec.push_back(*it);
      it = mylist.erase(it);
      if(it != mylist.begin())
         it--;
   }
}

Could anyone please help me to improve this algorithm? Thanks!
Mar 6, 2013 at 5:10pm
Why do you need to erase the entry in the list? Also your implementation seems to be missing one of your ones.

1
2
3
4
5
   for(auto it = mylist.begin(); it != mylist.end(); it++) {
      if(*it == 1) {
         myvec.push_back(*it);
      }
   }


Also if you are are always going to push the same number into your vector maybe you just want to count the number of times this number exists in your list then construct your list with correct number of elements and the default value:

// After counting the number of ones.
std::vector<int>myvec(NumberOfOnes,1);

Mar 6, 2013 at 5:30pm
Thanks for the reply.

But this is a very simplified version of my code. The original is very complexe. I have to erase all elements of 1 from the list, one by one. And push_back the vector of elements of 1, one by one.

Otherwise it would be too easy to make it.
Mar 6, 2013 at 6:23pm
Then I don't understand the problem. You say you must push_back the vector, and remove them from the list one by one. That's basically what you're doing. You do seem to be missing one element, I count 4 ones but the code you provided only pushes 3 to the vector.

The only speed up I can see would be to construct your vector with the same size as your list. Then you could use array access instead of the expensive push_back(). If you keep a count of the number of items deleted you can then resize the vector after the loop.
Mar 6, 2013 at 6:41pm
yes you are right, the second 1 is still in the list. I have to correct this... thanks

Please feel free to help if anyone is interested. just erase one by one from list, and add one by one to vector...
Last edited on Mar 6, 2013 at 6:50pm
Mar 6, 2013 at 6:58pm
I would do this

1
2
3
4
5
6
7
8
9
10
11
12
13
it = mylist.begin();
while(it != mylist.end())
{
  if(*it == 1)
  {
    myvec.push_back(*it);
    it = mylist.erase(it); // erase returns iterator to next element
  }
  else
  {
    ++it;
  }
}

Mar 6, 2013 at 7:16pm
Thanks. How about this? Is this one slower? (imagine with list of 10 million elements)
1
2
3
4
5
6
7
8
9
10
	for(auto it = mylist.begin(); it != mylist.end(); it++)
	{
		while(*it == 1)
		{
			myvec.push_back(*it);
			it = mylist.erase(it);
			if(it != mylist.begin())
				it--;
		}
	}
Last edited on Mar 6, 2013 at 7:26pm
Mar 6, 2013 at 7:19pm
Actually this seemed to work for me:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
   list<int> mylist = {1, 1, 1, 0, 0, 1, 0, 0};
   vector<int> myvec(mylist.size());
   size_t counter = 0;
   for(auto it = mylist.begin(); it != mylist.end(); it++) {
      if(*it == 1) {
         myvec[counter++] = (*it);
         it = mylist.erase(it);
         it--;
      }
   }
   myvec.resize(counter);
   cout << myvec.size() << endl;
   return(0);
}
]
Mar 6, 2013 at 7:28pm
Yes, this one is good by saving time of reallocate vector...
Topic archived. No new replies allowed.