En utilisant la récursivité et les retours en arrière pour générer toutes les combinaisons possibles

Je suis en train de mettre en œuvre une classe qui permettra de générer de tous les possibles non ordonnée de n-tuples ou les combinaisons d'un certain nombre d'éléments et la taille de la combinaison.

En d'autres termes, lors de l'appel de cette:

NTupleUnordered unordered_tuple_generator(3, 5, print);
unordered_tuple_generator.Start();

print() étant une fonction de rappel définie dans le constructeur.
La sortie doit être:

{0,1,2}
{0,1,3}
{0,1,4}
{0,2,3}
{0,2,4}
{0,3,4}
{1,2,3}
{1,2,4}
{1,3,4}
{2,3,4}

C'est ce que j'ai à ce jour:

class NTupleUnordered {
public:
    NTupleUnordered( int k, int n, void (*cb)(std::vector<int> const&) );
    void Start();
private:
    int tuple_size;                            //how many
    int set_size;                              //out of how many
    void (*callback)(std::vector<int> const&); //who to call when next tuple is ready
    std::vector<int> tuple;                    //tuple is constructed here
    void add_element(int pos);                 //recursively calls self
};

et c'est la mise en œuvre de la fonction récursive, Start() est juste un coup de pouce de la fonction d'avoir une interface épurée, elle n'appelle add_element(0);

void NTupleUnordered::add_element( int pos )
{

  //base case
  if(pos == tuple_size)
  {
      callback(tuple);   //prints the current combination
      tuple.pop_back();  //not really sure about this line
      return;
  }

  for (int i = pos; i < set_size; ++i)
  {
    //if the item was not found in the current combination
    if( std::find(tuple.begin(), tuple.end(), i) == tuple.end())
    {
      //add element to the current combination
      tuple.push_back(i);
      add_element(pos+1); //next call will loop from pos+1 to set_size and so on

    }
  }
}

Si je voulais générer toutes les combinaisons possibles d'une taille constante N, permet de dire que les combinaisons de taille 3 que je pouvais faire:

for (int i1 = 0; i1 < 5; ++i1) 
{
  for (int i2 = i1+1; i2 < 5; ++i2) 
  {
    for (int i3 = i2+1; i3 < 5; ++i3) 
    {
        std::cout << "{" << i1 << "," << i2 << "," << i3 << "}\n";
    }
  }
}

Si N n'est pas une constante, vous avez besoin d'une fonction récursive, qui imite le ci-dessus
la fonction par l'exécution de chaque boucle for dans son propre cadre. Lorsque, pour la boucle se termine,
programme renvoie à l'image précédente, en d'autres termes, les retours en arrière.

J'ai toujours eu des problèmes avec la récursivité, et maintenant j'ai besoin de le combiner avec des retours en arrière pour générer toutes les combinaisons possibles. Tous les pointeurs de ce que je fais mal? Ce que je devrais faire ou je suis dominant?

P. S: C'est un collège d'affectation, qui comprend également essentiellement faire la même chose à l'ordre n-tuples.

Merci d'avance!

/////////////////////////////////////////////////////////////////////////////////////////

Voulais juste faire un suivi avec le bon code, juste au cas où quelqu'un d'autre se pose la question de la même chose.

void NTupleUnordered::add_element( int pos)
{

  if(static_cast<int>(tuple.size()) == tuple_size)
  {
    callback(tuple);
    return;
  }

  for (int i = pos; i < set_size; ++i)
  {
        //add element to the current combination
        tuple.push_back(i);
        add_element(i+1); 
        tuple.pop_back();     
  }
}

Et pour le cas de l'ordre de n-tuples:

void NTupleOrdered::add_element( int pos )
{
  if(static_cast<int>(tuple.size()) == tuple_size)
  {
    callback(tuple);
    return;
  }

  for (int i = pos; i < set_size; ++i)
  {
    //if the item was not found in the current combination
    if( std::find(tuple.begin(), tuple.end(), i) == tuple.end())
    {
        //add element to the current combination
        tuple.push_back(i);
        add_element(pos);
        tuple.pop_back();

    }
  }
}

Merci Jason pour vos approfondie de la réponse!

Au lieu de stocker vos résultats jusqu'à présent dans une variable membre, vous pouvez les passer en argument à la fonction récursive. Il serait probablement aide afin de comprendre la logique.
L'affectation exige que je les stocker, mais peut-être que ça va m'aider à mieux le comprendre. Merci pour les conseils, je vais essayer.
Une autre chose, pos est juste la taille de votre tuple vecteur, de sorte que vous devriez être en utilisant tuple.size() à la place.
vous avez raison sur l'utilisation de tuple.size(), merci pour cette remarque

OriginalL'auteur Lechuzza | 2012-03-04