J'ai essayé d'implémenter un programme d'exemple backtracking en utilisant un conteneur std::queue
, dans le dialecte C++ 11. Cependant, il existe une erreur de codage quelque part dans l'algorithme qui provoque l'épuisement du programme. Quelle est cette erreur?Backtrack non récursif utilisant la file d'attente: manque de mémoire
Dans l'exemple de code ci-dessous, les fonctions reject()
, accept()
, first_child()
et next_child()
peuvent être supposés fonctionner correctement, parce qu'ils ont été testés avec succès avec le récipient récursive et std::stack
implementations of backtracking.
// helper functions
bool reject(const std::string &c);
bool accept(const std::string &c);
const std::string * first_child(const std::string &c); // nullptr == no child
const std::string * next_child(const std::string &c); // nullptr == no child
void backtrack_que(const std::string &start)
try
{
std::queue<std::string> que;
que.push(start);
while (!que.empty())
{
if (reject(que.front()))
{
que.pop();
continue;
}
if (accept(que.front()))
std::cout << que.front() << '\n';
const std::string *p_child(first_child(que.front()));
que.pop();
if (p_child != nullptr)
{
que.push(*p_child);
const std::string *p_sibling(next_child(que.back()));
while (p_sibling != nullptr)
{
que.push(*p_sibling);
p_sibling = next_child(que.back());
}
}
}
}
catch (...)
{
std::cerr << "unknown exception in `" << __func__ << '`' << std::endl;
throw;
}
Pour chaque chaîne, vous ajoutez 36 chaînes plus longues. Si vous commencez par une chaîne vide, vous obtiendrez 36^5 = 60 + millions de chaînes dans la file d'attente, ce qui, selon une estimation approximative, nécessiterait plus de 1 Go de RAM. Si vous commencez avec une chaîne de plus de 5 caractères, votre boucle ne s'arrête jamais du tout. –
@IgorTandetnik Merci d'avoir repéré le bug 'longueur> 5' dans' first_child() '. En ce qui concerne le bug de mémoire insuffisante, j'ai de la difficulté à comprendre pourquoi cela ne se produit pas lorsque 'std :: stack' est utilisé. – user7023624
La version de la pile a le même problème, autant que je sache. Je suppose que 'std :: stack' utilise' std :: vector' en dessous alors que 'std :: queue' utilise' std :: deque'. Ce dernier a des frais généraux un peu plus élevés par élément. Ainsi, vos chaînes 60 + M parviennent juste à s'intégrer dans la RAM avec la pile, mais sont épuisées avec la file d'attente. –