逐次探索

検索か探索か

記録されたデータから目的の物をコンピュータに見つけ出させることはよくある。その多くは辞典の中から言葉を探すような作業なので「検索」と言う言葉が使われてきた。日常的にも「辞書を探索する」とは言わず「辞書を検索する」という。

英語ではこのコンピュータの作業をsearchという。これを速くさせる方法はよく研究されていて、binary search が有名であるが、日本語ではこれを「二分検索」と言っていた。googleで検索して(この場合探索とは言わない)発見される件数を調べると2014年1月の時点で次のようになる。

二分検索 約 1,430,000 件
二分探索  約 769,000 件
>

ただし、Wikipediaではどちらで検索しても「二分探索」の項目が出てくる。冒頭には「二分検索、バイナリサーチともいう」とある。そして解説文では「ソート済みのリストや配列に入ったデータ(同一の値はないものとする)に対する検索を行うにあたって、 中央の値を見て、検索したい値との大小関係を用いて、検索したい値が中央の値の右にあるか、左にあるかを判断して、片側には存在しないことを確かめながら検索していく。」というように一貫して検索という言葉を用いている。

たぶん binary search の訳語として 二分探索 を定めたのでそれに従ったということなのでしょう。 searchを「探索」、retrievalを「検索」としたようです。機械翻訳などへの応用のしやすさという意味で機械的に翻訳しようとしているのかもしれませんが、それぞれの言語でのニュアンスがありますから"search"なら「探索」と一対一で対応付けるのは無理な場合もあります。「探索」には何が出てくるかやってみなければわからないという「探検」のニュアンスがあり、辞典を引くなどの行為は「検索」がふさわしいでしょう。

逐次探索-片っ端からさがすだけ-

見つかるまで順番に探します。

ファイル名 Chikuji01.java

public class Chikuji01 { 
    public static void main( String[] args ) {
        int[] data = { 11, 24, 36, 42, 58, 63, 77 };  //intの配列の宣言
        for ( int i=0 ; data.length>i ; i++ ){        //dataの要素全部について繰り返す
            if ( data[i] == 36 ){
                System.out.println( "発見" );          //発見と表示
            }
        }//forの終わり
    }//mainの終わり 
}//classの終わり

コンパイルと実行は次のようにします。

$ javac Chikuji01.java
$ java Chikuji01
発見
$ 

配列

int[] data = { 11, 24, 36, 42, 58, 63, 77 };

data[0]data[1]data[2]data[3] data[4]data[5]data[6]
11243642 586377

配列の要素数は data.length で調べることができます。0〜6 なら 7 です。

探す過程を表示

どうやって探したかもわかるようにしてみます。

ファイル名 Chikuji02.java

public class Chikuji02 { 
    public static void main( String[] args ) {
        int[] data = { 11, 24, 36, 42, 58, 63, 77 };  //intの配列の宣言
        for ( int i=0 ; data.length>i ; i++ ){        //dataの要素全部について繰り返す
            System.out.println( data[i] );
            if ( data[i] == 36 ){
                System.out.println( "発見" );          //発見と表示
            }
        }//forの終わり
    }//mainの終わり 
}//classの終わり

コンパイルと実行は次のようにします。

$ javac Chikuji02.java
$ java Chikuji02
11
24
36
発見
42
58
63
77
$ 

見つかってもさらに探し続けています。もし、36が2つ以上あっても全部見つけることができます。

ひとつ見つかったら終わりにする

36が一つしかなければ、見つかった後も探し続けるのは無駄です。ひとつ見つかったらforの残りの部分はやらないようにします。break はBASICの exit for に相当します。

ファイル名 Chikuji03.java

public class Chikuji03 { 
    public static void main( String[] args ) {
        int[] data = { 11, 24, 36, 42, 58, 63, 77 };  //intの配列の宣言
        for ( int i=0 ; data.length>i ; i++ ){        //dataの要素全部について繰り返す
            System.out.println( data[i] );
            if ( data[i] == 36 ){
                System.out.println( "発見" );          //発見と表示
                break;
            }
        }//forの終わり
    }//mainの終わり 
}//classの終わり

コンパイルと実行は次のようにします。

$ javac Chikuji03.java
$ java Chikuji03
11
24
36
発見
$ 

発見後すぐに終わっています。

探索する値を後で入力します

まえにも使ったJOptionPane.showInputDialog()を用いて36以外の数も探せるようにします。importを忘れないように。

ファイル名 Chikuji04.java

import javax.swing.*;

public class Chikuji04 { 
    public static void main( String[] args ) {
        int[] data = { 11, 24, 36, 42, 58, 63, 77 };  //intの配列の宣言
        int n;
        String s;
        s = JOptionPane.showInputDialog("検索する整数を入れてください?");
        n = Integer.parseInt(s);
        for ( int i=0 ; data.length>i ; i++ ){        //dataの要素全部について繰り返す
            System.out.println( data[i] );
            if ( data[i] == n ){
                System.out.println( "発見" );          //発見と表示
                break;
            }
        }//forの終わり
    }//mainの終わり 
}//classの終わり

コンパイルと実行は次のようにします。

$ javac Chikuji04.java
$ java Chikuji04  (ダイアログがでます。58と入力したとすると)
11
24
36
42
58
発見
$ 

英和辞典を作る

英単語を一覧から探して対応する日本語を表示すれば、辞書をつくったことになります。まず、5つぐらいで試してみます。Chikuji04.java に対して変わるところをこの色で示しましたが、削除される部分は書いてありません。

ファイル名 Jiten01.java

import javax.swing.*;

public class Jiten01 { 
    public static void main( String[] args ) {
        String[] word = { "blue", "green", "red", "yellow", "white" };
        String[] imi  = { "青", "緑", "赤", "黄", "白" };
        String s;
        s = JOptionPane.showInputDialog("検索する英単語を入れてください?");
        for ( int i=0 ; word.length>i ; i++ ){
            if ( word[i].equals(s) ){
                System.out.println( word[i]+" : "+imi[i] );
                break;
            }
        }//forの終わり
    }//mainの終わり 
}//classの終わり

コンパイルと実行は次のようにします。

$ javac Jiten01.java
$ java Jiten01  (ダイアログがでます。redと入力したとすると)
red : 赤
$ 

Stringが等しいかどうかは == でなく、.equals() を使います。

単語が見つからない時

単語が見つからない時に「見つかりません」と報告するようにしてみます

ファイル名 Jiten02.java

import javax.swing.*;

public class Jiten02 { 
    public static void main( String[] args ) {
        String[] word = { "blue", "green", "red", "yellow", "white" };
        String[] imi  = { "青", "緑", "赤", "黄", "白" };
        String s;
        s = JOptionPane.showInputDialog("検索する英単語を入れてください?");
        boolean atta=false;
        for ( int i=0 ; word.length>i ; i++ ){
            if ( word[i].equals(s) ){
                System.out.println( word[i]+" : "+imi[i] );
                atta=true;
                break;
            }
        }//forの終わり
        if ( atta==false ) System.out.println( "見つかりません" );
    }//mainの終わり 
}//classの終わり

コンパイルと実行は次のようにします。

$ javac Jiten02.java
$ java Jiten02  (ダイアログがでます。blackと入力したとすると)
見つかりません
$ 

boolean はintと同様に変数の型で、trueとfalseのどちらかの値しかとらない変数です。

ifのあとにさせる命令が1つだけの時は { } を省略できます。