これは、中央値アルゴリズムの中央値の擬似コードです(例に合わせて少し変更されています)。ウィキペディアの疑似コードは、selectIdx
関数呼び出しの内部動作を描写できません。
説明のためにコードにコメントを追加しました。
// L is the array on which median of medians needs to be found.
// k is the expected median position. E.g. first select call might look like:
// select (array, N/2), where 'array' is an array of numbers of length N
select(L,k)
{
if (L has 5 or fewer elements) {
sort L
return the element in the kth position
}
partition L into subsets S[i] of five elements each
(there will be n/5 subsets total).
for (i = 1 to n/5) do
x[i] = select(S[i],3)
M = select({x[i]}, n/10)
// The code to follow ensures that even if M turns out to be the
// smallest/largest value in the array, we'll get the kth smallest
// element in the array
// Partition array into three groups based on their value as
// compared to median M
partition L into L1<M, L2=M, L3>M
// Compare the expected median position k with length of first array L1
// Run recursive select over the array L1 if k is less than length
// of array L1
if (k <= length(L1))
return select(L1,k)
// Check if k falls in L3 array. Recurse accordingly
else if (k > length(L1)+length(L2))
return select(L3,k-length(L1)-length(L2))
// Simply return M since k falls in L2
else return M
}
あなたの例を取る:
中央値関数の中央値は、(with k = 45/2 = 22
)のように 45 要素の配列全体に対して呼び出されます。
median = select({48 49 50 51 52 43 44 45 46 47 38 39 40 41 42 33 34 35 36 37 28 29 30 31 32 23 24 25 26 27 18 19 20 21 22 13 14 15 16 17 8 9 10 53 54}, 45/2)
初めてM = select({x[i]}, n/10)
呼び出されると、配列{x[i]}
には次の番号が含まれます: 50 45 40 35 30 20 15 10
. この呼び出しでn = 45
は、したがって、select 関数呼び出しは次のようになります。M = select({50 45 40 35 30 20 15 10}, 4)
2 回目M = select({x[i]}, n/10)
に呼び出されると、配列{x[i]}
には次の番号が含まれます: 40 20
. この呼び出しではn = 9
、したがって、呼び出しは になりますM = select({40 20}, 0)
。この select 呼び出しは値を返し、割り当てますM = 20
。
さて、あなたが疑問に思った点に来て、配列L
をM = 20
で分割しk = 4
ます。
ここで配列を覚えておいてくださいL
: 50 45 40 35 30 20 15 10
.
配列は、規則に従っておよびに
分割されます。したがって
、 である
ため、 より大きいです。したがって、検索は次の再帰呼び出しで続行されます。
これは次のよう
に変換されます。
L1, L2
L3
L1 < M
L2 = M
L3 > M
L1: 10 15
L2: 20
L3: 30 35 40 45 50
k = 4
length(L1) + length(L2) = 3
return select(L3,k-length(L1)-length(L2))
return select({30 35 40 45 50}, 1)
結果として 30 が返されます。(L には 5 つ以下の要素があるため、k 番目、つまり並べ替えられた配列の 1 番目の位置 (30) の要素を返します)。
これで、 45 要素の配列全体に対するM = 30
最初のselect
関数呼び出しで受信され、配列を分離する同じ分割ロジックL
がM = 30
適用され、最終的に中央値の中央値が取得されます。
ふぅ!中央値アルゴリズムの中央値を説明するのに十分なほど冗長で明確であったことを願っています。