javaらしい並べ替え

クラスでバブル

まず、いままでのバブルソートではどのようになるかをやってみます。

プログラム名 OokiiJun41.java (に入れるソート部分)

OokiiJun41 tmp ;
for( int jn = 0; jn<ct-1; jn++ ){
    for( int i=0; i<ct-1-jn; i++ ) {
        if( jtable[i].soukei < jtable[i+1].soukei ){
             tmp       = jtable[i];   //この3行で値の交換
             jtable[i]   = jtable[i+1];
             jtable[i+1] = tmp;
        }
    }
}

結果

n2026 75 94 84 88 96 437
n1121 68 92 100 90 82 432
n1632 71 82 96 89 94 432
n1453 61 93 96 90 91 431
n1301 81 86 92 92 78 429
n1297 68 86 100 89 82 425
n1457 66 94 100 91 73 424
n1127 73 82 100 80 88 423
n1327 75 93 92 74 89 423
n1490 62 97 92 86 85 422

n1177 45 29 12 26 23 135
n1260 15 30 40 24 26 135
n1380 23 27 33 28 24 135
n2063 32 17 45 18 21 133
n1293 29 12 44 29 18 132
n1819 23 37 36 17 18 131
n2017 53 14 25 19 15 126
n1914 42 15 25 20 22 124
n1956 29 11 25 16 37 118
n1808 17 24 29 21 18 109

javaが持っているソートの仕組み

いままで、いろいろなソート(並べ替え)の方法を実際にプログラムを作って試してきましたが、javaにはソートの仕組みが組み込まれています。

Arrays.sort(配列, int fromIndex, int toIndex)とすれば、配列[fromIndex]から配列[toIndex-1]までが小さい順に並べ替えられます。指定された配列を直接並び替えます。

toIndex に注意してください。仕様には、「ソート範囲はインデックス fromIndex (範囲内) からインデックス toIndex (範囲外)」とあります。

ただし配列が何の配列かも問題です。intやdoubleなど大小関係が確定している変数の配列である場合にはこれでいいのですが、今回は自作のクラスの並べ替えなので、どう並べ替えるかを決めてjavaに教えなければなりません。そのために比較のためのクラスをつくります。

どちらが大きいか判断するクラス

そう難しくありません。2つのインスタンスを持ってきた時にどちらが大きいか判断する方法がわかればいいのです。

比較のためのクラスにはどんなクラスのインスタンスを比較するかを書いておく必要がありますから、まず今回のクラス名を決めます。

プログラム名 OokiiJun42.java

このクラスは OokiiJun42 用のものであることを、<OokiiJun42>で示しています。

たった一つのメソッド compare がありますが、2つの OokiiJun42 のインスタンスを x, y として、y が大きければ + の値、小さければ - の値を返すようにします。

ここでは OokiiJun42 のインスタンスの soukei 部分を引き算することでそれを表しています。

return * で * の値をメソッドの結果として返しています。

class SoukeiComp implements Comparator<OokiiJun42>{
    public int compare(OokiiJun42 x, OokiiJun42 y) {
         return y.soukei - x.soukei;
    }
}

javaのドキュメントでは「最初の引数が 2 番目の引数より小さい場合は負の整数、両方が等しい場合は 0、最初の引数が 2 番目の引数より大きい場合は正の整数を返します。」とありますが、こうすると小さい順(昇順)になります。ここでは大きい順(降順)にするため逆になっています。

javaには逆順にするという文法がないため、ここを逆に設定せざるを得ない場合があるでしょうが、ドキュメントのような解釈では理解し辛いのです。そこで次の様に考えることにしました。「2つの引数の順序が並べ替える必要が無いものなら負、等しい場合は0、並び替える必要があるなら正を返します。」

このクラスは別のファイルで保存してもいいですが(その場合は名前はSoukeiComp.java)、OokiiJun42.javaの最後に書き加えるのが手軽です。

こちらの場合は、ひとつのファイルの中にクラスが並びます。publicは一つだけにしないといけないのでSoukeiCompはpublicにしません。

public class OokiiJun42 {
    ................
}
class SoukeiComp implements Comparator<OokiiJun42>{
    ................
}

インポート

インポート文の追加が必要です。ComparatorとArraysのためです。

import java.util.*;

または

import java.util.Comparator;
import java.util.Arrays;

プログラムの中でのソート部分

ソートをしたいところで、上記で定義した SoukeiComp クラスを使用します。

Arrays.sort(jtable, 0, ct,new SoukeiComp());

jtable の 0 から ct-1 までを SoukeiComp を使ってソートするという意味です。

結果

当然ですが、OokiiJun41.java と同じです。

課題

1.

プログラム名 OokiiJun41.java

OokiiJun41に上記のバブルソートの部分を加えてソートを完成させなさい

2.

プログラム名 OokiiJun42.java

OokiiJun41のバブルソートの部分をArrays.sort を使って、javaらしい並べ替えにします。

まず、OokiiJun41をコピーしてOokiiJun42とし、プログラム中の OokiiJun41 をすべて OokiiJun42 にします。

ソート部分を、Arrays.sort(jtable, 0, ct,new SoukeiComp());を使って書き直します。

class SoukeiComp の追加と、インポート文の追加も忘れずに。

うまくいったら小さい順(昇順)にしてみましょう(class SoukeiComp の compare メソッドを変更することになります)

小さい順(昇順)の結果はこちら

n1808 17 24 29 21 18 109
n1956 29 11 25 16 37 118
n1914 42 15 25 20 22 124
n2017 53 14 25 19 15 126
n1819 23 37 36 17 18 131
n1293 29 12 44 29 18 132
n2063 32 17 45 18 21 133
n1169 36 18 33 28 20 135
n1177 45 29 12 26 23 135
n1260 15 30 40 24 26 135
n1380 23 27 33 28 24 135

n1795 72 87 96 91 76 422
n2046 62 88 96 92 84 422
n1127 73 82 100 80 88 423
n1327 75 93 92 74 89 423
n1457 66 94 100 91 73 424
n1297 68 86 100 89 82 425
n1301 81 86 92 92 78 429
n1453 61 93 96 90 91 431
n1121 68 92 100 90 82 432
n1632 71 82 96 89 94 432
n2026 75 94 84 88 96 437
もくじ

Javaプログラミング
聖愛中学高等学校
http://www.seiai.ed.jp/
Dec.2003
Feb.2009
Dec.2011