読者です 読者をやめる 読者になる 読者になる

マージソート

perl アルゴリズム

perlのsort関数はマージソートを使っているということなので、
勉強のため、perlマージソートするプログラムを書きました。

use strict;
use warnings;


{
    my @a = (8,4,3,9,7,6,5,2,1);
    print join(',',@a), "\n";
    print "===================\n";
    print join(',',sort(@a)), "\n";
}


#                                                                                              
# 二つの配列リファレンスを受け取って、並び替えながらマージする                                 
#                                                                                              

sub merge {
    my ($a1, $a2) = @_;

    my $i = 0;
    my $j = 0;

    my $a1_length = @$a1;
    my $a2_length = @$a2;

    my @new_a = ();

    while ($i < $a1_length || $j < $a2_length) {
        if ($j >= $a2_length || ($i < $a1_length && $a1->[$i] < $a2->[$j])) {
            $new_a[$i+$j] = $a1->[$i];
            $i++;
        } else {
            $new_a[$i+$j] = $a2->[$j];
            $j++;
        }
    }

    return @new_a;
}


#                                                                                              
# 一つの配列を受け取って、要素が2以上だったら二つの配列に分解して、それぞれの配列をマージソートする。                                                                                       
# マージソートされた二つの配列をマージする。                                                   
#                                                                                              

sub merge_sort {
    my @a = @_;

    my $a_length = @a;
    my @new_a = ();

    if ($a_length > 1) {
        my $m = $a_length / 2;
        my $n = $a_length - $m;

        my @a1 = ();
        my @a2 = ();

        for (my $i = 0; $i < $m; $i++) {
            $a1[$i] = $a[$i];
        }

        for (my $i = 0; $i < $n; $i++) {
            $a2[$i] = $a[$m+$i];
        }

        @a1 = merge_sort(@a1);
        @a2 = merge_sort(@a2);
        @new_a = merge(\@a1, \@a2);
    }

    return @new_a;
}


sub sort {
    my @a = @_;
    return merge_sort(@a);
}


マージソートの特徴として下記のようなものがあるみたいですね。

  • 直接アクセスできないリスト構造でもソートを行なえる
  • 一時的に大きなメモリ空間が必要
  • 元データの状態によって性能が大きく変化しない(安定なソートアルゴリズム)
  • O(nlogn)
  • 比較的高速なソート(クイックソートほどではない)