N 項目のリストから N 長の順列を再帰的に生成する一般的なアルゴリズムは次のとおりです。
リスト内の各要素 x について
- 要素 x を含まないリストのコピーを作成します。それをnewListと呼ぶ
- newList のすべての順列を検索します (これが再帰です)
- newList の各順列の先頭に要素 x を追加します
これを行う方法は他にもありますが、再帰を学んでいる人にとって頭を包み込むのが最も簡単であると一貫してわかっている方法です。あなたが使用しているように見える方法は、アルゴリズムの反復ループ部分を2番目のリストに格納することを含みます. -疑いがやがて発見されます)。
以下は、一般的なアルゴリズムを示しています (特に効率的ではありませんが、そこから一般的なアイデアを得ることができます)。
#include <iostream>
#include <list>
typedef std::list<int> IntList;
void iterlist(IntList& lst)
{
for (IntList::iterator it=lst.begin(); it!=lst.end(); it++)
cout << " " << *it;
cout << endl;
}
std::list<IntList> permute(IntList& L1)
{
if (L1.size() == 1)
return std::list<IntList>(1,L1);
std::list<IntList> res;
for (IntList::iterator i = L1.begin(); i != L1.end();)
{
// remember this
int x = (*i);
// make a list without the current element
IntList tmp(L1.begin(), i++);
tmp.insert(tmp.end(), i, L1.end());
// recurse to get all sub-permutations
std::list<IntList> sub = permute(tmp);
// amend sub-permutations by adding the element
for (std::list<IntList>::iterator j=sub.begin(); j!=sub.end();j++)
(*j).push_front(x);
// finally append modified results to our running collection.
res.insert(res.begin(), sub.begin(), sub.end());
}
return res;
}
int main()
{
IntList lst;
for (int i=0;i<4;i++)
lst.push_back(i);
std::list<IntList> res = permute(lst);
for (std::list<IntList>::iterator i=res.begin(); i!=res.end(); i++)
iterlist(*i);
return 0;
}
次の出力を生成します。すべての順列は 0..3 です。
3 2 1 0
3 2 0 1
3 1 2 0
3 1 0 2
3 0 2 1
3 0 1 2
2 3 1 0
2 3 0 1
2 1 3 0
2 1 0 3
2 0 3 1
2 0 1 3
1 3 2 0
1 3 0 2
1 2 3 0
1 2 0 3
1 0 3 2
1 0 2 3
0 3 2 1
0 3 1 2
0 2 3 1
0 2 1 3
0 1 3 2
0 1 2 3