3

The basic structure of my code is:

using namespace std;
void recursiveFunction(list <int> &jobs,...){
list<int>::iterator i;
int ii;
//code missing
    for(i=jobs.begin(); i != jobs.end(); ++i){
        //more code missing
        list<int>::iterator tempi(i);
        ii=*i;
        jobs.erase(tempi);
        recursiveFunction(jobs,...);
        jobs.insert(i,ii);
    }
}

As I have discovered, any pointer pointing to a position that is erased is invalidated, so i is invalidated. Is there some way to reinsert the job numbers in this way? Without the performance hit of creating a new list each recursion?

Is there a way to use something other than a list iterator, perhaps?

DylanTheWebb
  • 33
  • 1
  • 1
  • 3
  • 3
    What exactly are you trying to do? It seems to me you try to erase an element and then insert it in the same place where it used to be – Ivaylo Strandjev Jun 18 '13 at 06:57
  • 1
    When iterating using `erase()` you have to use the return value of the function for the further iteration. – Mario Jun 18 '13 at 07:08
  • After all those erases in recursive call, iterator i is decayed, so why don't use push_back instead of insert? – Spoonwalker Highwater Jun 18 '13 at 07:28
  • the same list is being read at multiple recursion levels, I don't think I can use push_back without the higher levels reading the same jobs twice... – DylanTheWebb Jun 18 '13 at 08:28

2 Answers2

8

list::erase returns an iterator to the element past the (last) erased element, and since list::insert will insert before the element whose iterator you pass it, that's perfect for your needs:

using namespace std;
void recursiveFunction(list <int> &jobs,...){
  //...
  for(auto i = begin(jobs); i != end(jobs);){ 
    //...
    auto tmpElem = *i;
    i = jobs.erase(i);
    recursiveFunction(jobs,...);
    jobs.insert(i,tmpElem);
  }
}

Notes:

  • with i=jobs.erase(i) you effectively increment i. So leave the increment in the for loop. Alternatively use i=jobs.insert(i,tmpElem) later, so i points to the same element again
  • Declare variables (e.g. i, tmpElem) as local as possible, as a matter of good style and maintainability
  • Give variables meaningful names

Depending on what the function does there might be other possibilities to achieve what you want. This way you will work on each subset of list elements, and on many of those multiple times. Consider the list to have the content {1,2,3}, heres' what is going to happen (in pseudo-code):

recursiveFunction({1,2,3},...)
  for-loop, i = &1
    erase(1)
    recursiveFunction({2,3},...)
      for-loop, i = &2
        erase(2)
        recursiveFunction({3},...)    //a
        insert(2)
      //...
    insert(1)
  for-looop, i = &2
    erase(2)
    recursiveFunction({1,3},...)
      for-loop, i = &1
        erase(1)
        recursiveFunction({3},...)    //b
        insert(1)
      //...
    insert(2)
  //...

Lines a and b look the same, although the additional parameters might not be the same - I can't tell from your code. So just keep it in mind and consider if this is what you actually want.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
  • Thanks so much! I should have said I am using this to enumerate job sequences, and exiting early if a job sequence is undesirable. – DylanTheWebb Jun 18 '13 at 08:23
0

Recursion does not seem to be the right tool for your problem. If you have a list containing { 1, 2, 3, 4 } and all three qualify, it looks like this is what would happen:

recurse({1,2,3,4});
  it.1 = (1)
  remove 1
  recurse({2,3,4});
    it.2 = (2)
    remove 2
    recurse({3,4});
      it.3 = (3)
      remove 3
      recurse({4});
        it.4 = (4)
        remove 4
        recurse({})
        reinsert 4 ({4})
      reinsert 3 ({3,4})
      it.3 = (4)
      remove 4
      recurse({3});
        it.4 = (3)
        remove 3
        recurse({})
        reinsert 3 ({3})
      reinsert 4 ({3,4})
    reinsert 2 ({2,3,4})
    it.2 = (3)
    remove 3 leaving ({2,4})
... etc ...
kfsone
  • 23,617
  • 2
  • 42
  • 74