単純挿入ソート (Shuttle Sort)

ブログエントリーさぼらないために比較的よく知られているシンプルなアルゴリズムを書いてみた。

単純挿入ソート (Shuttle Sort) を書いてみました。

特徴としてトランプのカードを順番に並び替えるようなアルゴリズムであり、安定であること。

効率はあまり良くなく、O(n^2) です。

具体的には i 番目の要素(0番目からじゃない) に着目して i –1 番目と比較してそれより小さければ後ろにずらして挿入する。

これを繰り返しているだけの単純なアルゴリズムです。

特別にトリッキーなことはしてなくて理解しやすいアルゴリズムですね。

プログラムにはソートされていく過程をトレースして出力させています。

package jp.yucchi.shuttlesort;

import java.security.SecureRandom;
import java.util.Arrays;
import java.util.stream.IntStream;

/**
 *
 * @author Yucchi
 */
public class ShuttleSort {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        int[] randomNumber = new SecureRandom().ints(10L, 1, 11).toArray();

        System.out.println("befor:" + Arrays.toString(randomNumber) + System.getProperty("line.separator"));

        insertionSort(randomNumber);

        System.out.println(System.getProperty("line.separator") + "after:" + Arrays.toString(randomNumber));

    }

    private static void insertionSort(int[] randomNumber) {
        IntStream.range(1, randomNumber.length).forEach(i -> {
            int j;
            int temp = randomNumber[i];
            for (j = i; j > 0 && randomNumber[j - 1] > temp; j--) {
                randomNumber[j] = randomNumber[j - 1];
            }
            randomNumber[j] = temp;
            trace(randomNumber);
        });
    }

    private static void trace(int[] randomNumber) {

        System.out.println("trace:" + Arrays.toString(randomNumber));

    }

}

このプログラムの実行結果は下図のようになります。

1

ちなみに Java8 を使っているので for 文でいいところを IntStream を使ったりしてます。

比較、入れ替えの for 文のところを Stream API を使ってできないものかと考えてみたのですが良いアイディアが浮かびませんでした。

配列の要素を並び替えるだけなので出来そうな気がしたのですが・・・(力不足、知恵不足、お小遣い不足)(ヲヒ

あっ、Stream API にはもちろん標準で sort の機能はあります。

だから本当はこんなアルゴリズム使う必要はありません!

そこんところ ヨロシク! by 永ちゃん

あと、乱数配列の生成は public IntStream ints(long streamSize,int randomNumberOrigin,int randomNumberBound) メソッドを使って生成しました。

超便利です!

今回もありきたりネタでした。(^_^)

Hatena タグ:

Java 8 時代の総和の求め方

Blog エントリーさぼりがちになるのでしょうもないネタを書いときます。

Java 8 になって Stream API がめっちゃ便利に使えてよろこんでいる開発者たちがたくさんいますよね!

中には仕事で未だに古い Java を使わざるを得ない非常に可愛そうな環境のひとも・・・(ヲヒ

で、おそらく春に入社してくるフレッシュな新人プログラマには Java 8 の Stream API を使った新しい構文を勉強してもらうことになりますよね?

今さら、JDK 1.4, JDK 1.5, JDK1.6, JDK1.7 なんてことはないですよね。ねっ!ねっ!

そこで、1 から 1000 までの偶数だけの総和を求め。

2 の 0 乗から 2 の 32 乗までの総和を求める。

この二つを題材にして超シンプルなプログラムを Java 8 で組むとどうなるでしょうか?

次のような感じで組んでしまったら、あなたは新人さんに影で static おじさん じゃない・・・ Stream おじさん と呼ばれることになるかもしれません。

package jp.yucchi.bad.summation;

import java.util.stream.DoubleStream;
import java.util.stream.IntStream;

/**
 *
 * @author Yucchi
 */
public class BadSummation {

    public static void main(String[] args) {

        // 1 から 1000 までの偶数だけの総和を求める。
        int sum = IntStream.rangeClosed(1, 1_000)
                .filter(e -> (e & 1) == 0)
                .sum();

        System.out.println("1 から 1000 までの偶数だけの総和は、" + sum + " です。");
        

        // 2 の 0 乗から 2 の 32 乗までの総和を求める。
        double powerSum = DoubleStream.iterate(0.0, i -> i + 1.0)
                .limit(32 + 1)
                .map(i -> Math.pow(2.0, i))
                .sum();

        System.out.println("2 の 0 乗から 2 の 32 乗までの総和は、" + powerSum + " です。");
    }

}

えっ?

こんな感じのプログラムしか思いうかばないって!

Stream おじさん に認定します!

このプログラムは Stream API の説明サンプルには問題ないのですが効率が悪いのです。

まじめに勉強をしてきた新人さんほどこういったところを突いてくると思うので先に古典的な手法で求める方法を見せといてから

無理に Stream API を使うとこうなるよって言っとくのが無難だと思います。

新人プログラマの多くは次のようなプログラムを当たり前のように組むでしょう。

Stream API なんて使わずに古典的な手法を用いてシンプルに!

package jp.yucchi.summation;

/**
 *
 * @author Yucchi
 */
public class Summation {

    public static void main(String[] args) {

        // 1 から 1000 までの偶数だけの総和を求める。
        int sum = 1_000 / 2 * (1_000 / 2 + 1);

        System.out.println("1 から 1000 までの偶数だけの総和は、" + sum + " です。");
        

        // 2 の 0 乗から 2 の 32 乗までの総和を求める。
        double powerSum = Math.pow(2.0, 32.0 + 1.0) - 1.0;

        System.out.println("2 の 0 乗から 2 の 32 乗までの総和は、" + powerSum + " です。");

    }

}

いつの時代になってもこういった定番の処理方法は不滅です!

ちなみに偶数の総和は「日経ソフトウェア3月号」の「アルゴリズム&テクニック」で紹介されてます。

今月は他にも面白ネタが紹介されていておもしろかった。

この総和を求めるアルゴリズムは古典的な手法で広く知られているようで

「アルゴリズムパズル プログラマのための数学パズル」という本でもちょこっとだけ紹介されていました。

たとえ、カビが生えているような技術でもいいものはいつまでも使われるってことですね! (^_^)

以上、しょうもないネタでした。

Hatena タグ: