配列のサイズがNで、Kがゼロ以外のエントリの数である場合は、次のようにします。
ARRAY_ELT_TYPE a[N];
int r[N];
for (i = 0; i < N; i++) { a[i] = 0; r[i] = i; }
for (i = 0; i < K; i++) {
swap(r[i], i + random_nonneg_less_than(N - i));
a[r[i]] = nonzero_value();
}
指摘したように、ゼロ以外の要素を配列の先頭に配置してシャッフルすることもできます。一度だけ初期化する場合、これは明らかに優れたアルゴリズムです。
上記のアルゴリズムの利点はa
、別のランダム行列に何度も再初期化する必要がある場合に得られます。ただ歩き回っr
てください。再初期化は必要ありません。K個の非ゼロ要素の後続の挿入はすべてKステップのみを必要とします。KがNに比べて小さい場合、これは大きな勝利になる可能性があります。
ARRAY_ELT_TYPE a[N];
int r[N];
// Initialize one time.
for (i = 0; i < N; i++) { a[i] = 0; r[i] = i; }
j = 0;
for (many, many iterations) {
// Insert non-zero values in K steps.
for (i = 0; i < K; i++) {
swap(r[i], i + random_nonneg_less_than(N - i));
a[r[i]] = nonzero_value();
}
//
// USE RANDOM ARRAY a HERE
//
// Re-zero a in only K steps.
for (i = 0; i < K; i++) a[r[i]] = 0;
}