「Heapのアルゴリズム」の版間の差分
混同「ヒープソート」 |
|||
10行目: | 10行目: | ||
異なる{{math|''n''}}要素の置換を考える。Heapはこれらの要素の各置換をそれぞれ1度だけ生成するために入れ替える要素のペアを選択する体系的方法を発見した。その方法を再帰的やりかたで説明しよう。まずカウンター{{math|''i''}}を0にセットする。そして以下のステップを{{math|''i''}}が{{math|''n''}}と等しくなるまで繰り返す。まず最後の要素と隣接する最初の{{math|''n''−1}}要素の置換{{math|(''n''−1)!}}個をアルゴリズムで生成する。これは最後の要素で終わる置換を全て生成する。次に{{math|''n''}}が奇数の場合最初の要素と最後の要素を入れ替え、{{math|''n''}}が偶数の場合は{{math|''i''}}番目の要素と最後の要素を入れ替える(最初のイテレーションでは{{math|''n''}}の偶奇で違いはない)。{{math|''i''}}に1を加算し、最初に戻る。各イテレーションでこのアルゴリズムは「最後」の位置に移動した要素で終わる全置換を生成する。以下の疑似コードは長さ{{math|''n''}}のデータ配列の全置換を出力する。 |
異なる{{math|''n''}}要素の置換を考える。Heapはこれらの要素の各置換をそれぞれ1度だけ生成するために入れ替える要素のペアを選択する体系的方法を発見した。その方法を再帰的やりかたで説明しよう。まずカウンター{{math|''i''}}を0にセットする。そして以下のステップを{{math|''i''}}が{{math|''n''}}と等しくなるまで繰り返す。まず最後の要素と隣接する最初の{{math|''n''−1}}要素の置換{{math|(''n''−1)!}}個をアルゴリズムで生成する。これは最後の要素で終わる置換を全て生成する。次に{{math|''n''}}が奇数の場合最初の要素と最後の要素を入れ替え、{{math|''n''}}が偶数の場合は{{math|''i''}}番目の要素と最後の要素を入れ替える(最初のイテレーションでは{{math|''n''}}の偶奇で違いはない)。{{math|''i''}}に1を加算し、最初に戻る。各イテレーションでこのアルゴリズムは「最後」の位置に移動した要素で終わる全置換を生成する。以下の疑似コードは長さ{{math|''n''}}のデータ配列の全置換を出力する。 |
||
< |
<syntaxhighlight lang="pascal"> |
||
procedure generate(n : integer, A : array of any): |
procedure generate(n : integer, A : array of any): |
||
if n = 1 then |
if n = 1 then |
||
24行目: | 24行目: | ||
end for |
end for |
||
end if |
end if |
||
</syntaxhighlight> |
|||
</source> |
|||
このアルゴリズムは非再帰的に書くこともできる。<ref>{{cite web|url=http://www.cs.princeton.edu/~rs/talks/perms.pdf|title=a talk on Permutation Generation Algorithms|accessdate=2018-06-03|last=Sedgewick|first=Robert|publisher=}}</ref> |
このアルゴリズムは非再帰的に書くこともできる。<ref>{{cite web|url=http://www.cs.princeton.edu/~rs/talks/perms.pdf|title=a talk on Permutation Generation Algorithms|accessdate=2018-06-03|last=Sedgewick|first=Robert|publisher=}}</ref> |
||
< |
<syntaxhighlight lang="pascal"> |
||
procedure generate(n : integer, A : array of any): |
procedure generate(n : integer, A : array of any): |
||
c : array of int |
c : array of int |
||
54行目: | 54行目: | ||
end if |
end if |
||
end while |
end while |
||
</syntaxhighlight> |
|||
</source> |
|||
== 関連項目 == |
== 関連項目 == |
2020年7月5日 (日) 23:10時点における版
Heapのアルゴリズムはn個のオブジェクトの全ての置換を生成するアルゴリズムである。1963年にB. R. Heapによって提案された。[1]このアルゴリズムは移動を最小化する。つまり、各置換は前の置換から1ペアを交換するだけで生成され、他のn−2要素を操作する必要はない。1977年の置換生成アルゴリズムの論評で、Robert Sedgewickはこのアルゴリズムをコンピュータによる現時点で最も効率的な置換生成用アルゴリズムと結論づけた。[2]
Heapのアルゴリズムによって生成されたn個のオブジェクトの置換列はn+1個のオブジェクトの置換列の最初になっている。したがってHeapのアルゴリズムは無限置換列を生成する(オンライン整数列大辞典の数列 A280318)。
概要
異なるn要素の置換を考える。Heapはこれらの要素の各置換をそれぞれ1度だけ生成するために入れ替える要素のペアを選択する体系的方法を発見した。その方法を再帰的やりかたで説明しよう。まずカウンターiを0にセットする。そして以下のステップをiがnと等しくなるまで繰り返す。まず最後の要素と隣接する最初のn−1要素の置換(n−1)!個をアルゴリズムで生成する。これは最後の要素で終わる置換を全て生成する。次にnが奇数の場合最初の要素と最後の要素を入れ替え、nが偶数の場合はi番目の要素と最後の要素を入れ替える(最初のイテレーションではnの偶奇で違いはない)。iに1を加算し、最初に戻る。各イテレーションでこのアルゴリズムは「最後」の位置に移動した要素で終わる全置換を生成する。以下の疑似コードは長さnのデータ配列の全置換を出力する。
procedure generate(n : integer, A : array of any):
if n = 1 then
output(A)
else
for i := 0; i < n; i += 1 do
generate(n - 1, A)
if n is even then
swap(A[i], A[n-1])
else
swap(A[0], A[n-1])
end if
end for
end if
このアルゴリズムは非再帰的に書くこともできる。[3]
procedure generate(n : integer, A : array of any):
c : array of int
for i := 0; i < n; i += 1 do
c[i] := 0
end for
output(A)
i := 0;
while i < n do
if c[i] < i then
if i is even then
swap(A[0], A[i])
else
swap(A[c[i]], A[i])
end if
output(A)
c[i] += 1
i := 0
else
c[i] := 0
i += 1
end if
end while
関連項目
脚注
- ^ Heap, B. R. (1963). “Permutations by Interchanges”. The Computer Journal 6 (3): 293–4. doi:10.1093/comjnl/6.3.293 .
- ^ Sedgewick, R. (1977). “Permutation Generation Methods”. ACM Computing Surveys 9 (2): 137–164. doi:10.1145/356689.356692.
- ^ Sedgewick, Robert. “a talk on Permutation Generation Algorithms”. 2018年6月3日閲覧。