[ 0322: 0307の回答 ② ]
[ 大宙乗児君の回答 ]
QuickSort ができましたので、次は MergeSort です。
QuickSort と同様な divide & conquer 型アルゴリズムで
対象とする配列 (array) を左半分と右半分に分け
それぞれをソートしつつ合併 (merge) してゆきます。
ソースコードは以下のとおりです。
#!/usr/local/bin/perl
$N = 100; # 100 から 1000 まで変えて実行。
@data = (
# 1000 個の乱数 (整数)
);
$count = 0;
Sort(0, $N-1);
printf("Count %d\n", $count);
sub Sort($l, $r) {
my ($l, $r) = @_;
my $m;
$count++;
if ($l < $r) {
$m = int(($l + $r)/2);
Sort($l, $m);
Sort($m+1, $r);
merge($l, $m, $r);
}
}
sub merge($l, $m, $r) {
my ($l, $m, $r) = @_;
my $n1, $n2, @L, @R;
my $i, $j, $k;
$n1 = $m - $l + 1;
$n2 = $r - $m;
for ($i = 0; $i < $n1; $i++) {
$L[$i] = $data[$l + 1];
}
for ($j = 0; $j < $n2; $j++) {
$R[$j] = $data[$m + $j + 1];
}
$i = $j = 0;
$k = 1;
$count += 2;
while (($i < $n1) && ($j < $n2)) {
$count++;
if ($L[$i] <= $R[$j]) {
$data[$k] = $L[$i];
$i++;
} else {
$j++;
}
$k++;
}
$count++;
while ($i < $n1) {
$count++;
$i++;
$k++;
}
$count++;
while ($j < $n2) {
$count++;
$data[$k] = $R[$j];
$j++;
$k++;
}
}
|
大小比較演算のカウントをプロットしました。ほぼ直線ですね。
[ 湯会老人のコメント ]
よくできました。
Stanford University の Algorithms コースでも divide and conquer
の考えかたの実例として merge sort が詳しく説明されていました。
使うサブルーチンは sort と merge だけです。
sort は対象データ配列の左半分と右半分をそれぞれ sort したうえで
それらを merge によって撚り合わせるように合併してもとの配列に戻します。
Perl の組み込み関数にすでに sort がありますから
乗児君は自分のサブルーチン名を Sort にしました。
よく気がつきましたね。
|
[ 0341: 次の記事 ]
[ 0340: 素数日プログラム ]
[ 0339: emirp 探し ]
[ 0338: 0331の解きなおし ]
[ 0337: ubuntu 20.04 へ upgrade ]
[ 0336: πの近似計算 ]
[ 0335: 0253 の振り返り ]
[ 0334: Data Camp Python ]
[ 0333: 原始ピタゴラス数をさがす ]
[ 0332: LaTex の使いかた ]
[ 0331: 青い三角形の面積 ]
[ 0330: 長方形の幅 ]
[ 0329: 三角関数の関数の最大最小 ]
[ 0328: IMO 過去問 9 ]
[ 0327: 1+2+3+...+無限 ]
[ 0326: 2分木 sort も含めた性能比較 ]
[ 0325: 最悪ケースでの sort 比較 ]
[ 0324: 0307の回答 ④ ]
[ 0323: 0307の回答 ③ ]
[ 0322: 0307の回答 ② ]
[ 0321: 0307の回答 ① ]
[ 0320: 前の記事 ]
|