std::queue
コンテナをC++ 11の方言で使用してbacktrackingサンプルプログラムを実装しようとしました。キューを使用した非再帰バックトラック:メモリ不足
ただし、アルゴリズムのどこかにコードミスがあり、プログラムのメモリが不足します。そのミスは何ですか?以下のサンプルコードで
それらが再帰とstd::stack
容器implementations of backtrackingで正常にテストされているので、機能reject()
、accept()
、first_child()
とnext_child()
は、正常に動作すると仮定することができます。
// 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;
}
ポップする各文字列に対して、36個の長い文字列を追加します。空の文字列で始めると、キューには36^5 = 60 + 100万文字の文字列があります。この文字列には、1GBのRAMが必要です。 5文字より長い文字列で始めると、ループはまったく停止しません。 –
@IgorTandetnik 'first_child()'に 'length> 5'バグを発見していただきありがとうございます。メモリ不足のバグについては、 'std :: stack'が使われてもなぜそれが起こらないのかを理解するのが難しいです。 – user7023624
スタックバージョンには、私が知る限り、同じ問題があります。私の推測では、 'std :: stack'は' std :: queue'が 'std :: deque'を使っている間に' std :: vector'を使っています。後者は要素ごとに幾分高いオーバーヘッドを持ちます。だからあなたの60 + Mの文字列は、スタックでRAMに収まるように管理しますが、キューは使い果たされます。 –