挿入ソートとデータ列の関係(中編)

では、さっそくソートに掛かる時間を計測したいと思います。

use strict;
use warnings;
use v5.10;
use Benchmark qw/cmpthese timethese/;
use Array::Shuffle qw/shuffle_array/;

{
    my $n = 10;
    my @data = 1..2000;

    my @data_asc_ary = map {
        my @tmp = @data;
        \@tmp;
    } 1..$n;

    my @data_rand_ary = map {
        my @tmp = @data;
        shuffle_array( @tmp );
        \@tmp;
    } 1..$n;

    cmpthese( $n, {
        'asc' => sub {
            my $ary_ref = shift @data_asc_ary;
            insert_sort( @{$ary_ref} );
        },
        'random' => sub {
            my $ary_ref = shift @data_rand_ary;
            insert_sort( @{$ary_ref} );
        }
    });
}

print "\n";

{
    my @data_asc  = 1..5000;
    my @data_desc = reverse @data_asc;

    timethese( 1, {
        'asc ' => sub {
            my @wk = @data_asc;
            insert_sort( @wk );
        },
        'desc' => sub {
            my @wk = @data_desc;
            insert_sort( @wk );
        }
    });
}

sub insert_sort {
    my @data = @_;

    my $cnt = scalar( @data );
    for (my $i=1; $i<$cnt; $i++) {
        my $wk = $data[$i];
        my $j = $i;
        for (; 0<$j; $j--) {
            if ( $wk <= $data[$j-1] ) {
                last;
            }
            else {
                $data[$j] = $data[$j-1];
            }
        }

        $data[$j] = $wk;
    }
 
    return @data;
}

結果はこんな感じ。

$ perl aaa.pl 
       s/iter    asc random
asc      1.38     --   -49%
random  0.696    98%     --

Benchmark: timing 1 iterations of asc , desc...
      asc :  9 wallclock secs ( 8.66 usr +  0.04 sys =  8.70 CPU) @  0.11/s (n=1)
            (warning: too few iterations for a reliable count)
      desc:  0 wallclock secs ( 0.00 usr +  0.00 sys =  0.00 CPU)
            (warning: too few iterations for a reliable count)

ランダムデータの場合と、小さい順に並んだデータだと、
だいたい倍くらいの差がつくようです。

そして、大きい順に並んだデータはソート済みのデータと等価なので、
ソートに掛かる時間が短過ぎて、他と比較のしようがないです。

あと、見直してて思ったのは、
シャッフルが無視できるようなデータ数でやれば、
もっとテストコードがシンプルかなーって思いました。

ここまではカンペ通りです。

続く。

Leave a Comment