0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rubyで線形探索と番兵法

Last updated at Posted at 2019-03-03

はじめに

この記事ではRubyで線形探索について解説していきます。

線形探索とは

線形探索とは最も単純なアルゴリズムの一つで、目的とする要素に出会うまで先頭から順に要素を走査(なぞるように探す)していくことです。

もっと単純に言うと先頭から末尾まで一つ一つ探していきます。

線形探索では値があるか値はどこにあるかなどを求めることができます。

また線形探索は逐次探索リニアサーチとも言います。

メリットとデメリット

メリット

線形探索のメリットは単純で実装がしやすいと言うことです。

デメリット

線形探索のデメリットは先頭から末尾まで一つ一つ調べるので処理が遅いと言うことです。

実装例

下記のコードでは線形探索の例を書いています。

linear_search.rb
# 配列aの先頭number個の要素からtargetと一致する要素を線形探索

def linear_search(a, number, target)
  #探索に失敗した場合は-1を返す
  i = 0
  loop do
    return -1 if i == number  #探索成功
    return  i  if a[i] == target #探索失敗
    i += 1
  end

end


puts "配列aの要素数を入力してください。"
number = gets.to_i
a = []

puts "配列に入る数字を入力してください"
number.times {|i|
  print "a[#{i}]:"
  a[i] = gets.to_i
}

puts "探したい値を入力してください"
print "探す値:"
target = gets.to_i

result = linear_search(a, number, target)

if result == -1
  puts "その値は存在しません。"
else
  puts "その値はa[#{result}]にあります。"
end

番兵法

番兵法とは探索する値と全く同じ値を、配列の一番後ろに置く探索の方法のことです。
番兵とは、そのとき格納する「探索する値と全く同じ値」のことのことです。

番兵を置く理由は探索するときのコストを抑えることです。

前回書いたの線形探索のコードでは、探索するときに毎回if文を2回繰り返します。

linear_search.rb
def linear_search(a, number, target)
  #探索に失敗した場合は-1を返す
  i = 0
  loop do
    return -1 if i == number  #探索成功
    return  i  if a[i] == target #探索失敗
    i += 1
  end
end

一方番兵法を使えばif文は1つですみます。

linear_search2.rb

def linear_search(a, number, target)
  #探索に失敗した場合は-1を返す
  i = 0
  a[number] = target #番兵を追加

  loop do
    break  if a[i] == target #探索成功
    i += 1
  end
  i == number ? -1 : i
end

最初のinear_search.rbに書いた線形探索では探索が成功したか判定するif文と探索が失敗したか判定するif文の2回を何度も繰り返します。
一方、linear_search2.rbに書いた番兵法では探索が成功した場合は、その時点で探索が終了します。これは線形探索と同じです。
そして探索が失敗したか判定するときは、線形探索ではなんども繰り返し判定していましたが、番兵法では末尾に番兵として目的の値が加えられているため、目的の値がない場合最後の探索で終了条件が成立します。
これにより、何度も終了条件を判定する必要がなくコストを抑えられます。

実装例

下記のコードが番兵法の実装例です。

linear_search2.rb
def linear_search(a, number, target)
  i = 0

  a[number] = target #番兵を追加
  loop do
    break  if a[i] == target #探索成功
    i += 1
  end
  i == number ? -1 : i
end


puts "配列aの要素数を入力してください。"
number = gets.to_i
a = []

puts "配列に入る数字を入力してください"
number.times {|i|
  print "a[#{i}]:"
  a[i] = gets.to_i
}

puts "探したい値を入力してください"
print "探す値:"
target = gets.to_i

result = linear_search(a, number, target)

if result == -1
  puts "その値は存在しません。"
else
  puts "その値はa[#{result}]にあります。"
end

最後に

以上で線形探索と番兵法についての解説を終わります。
何か間違っていることがあったらご指摘ください。

参考

以下の書籍を参考にしました。

新・明解 Javaで学ぶアルゴリズムとデータ構造
https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3-Java%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-%E6%9F%B4%E7%94%B0-%E6%9C%9B%E6%B4%8B-ebook/dp/B0722XVC7D/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?