質問文
アルゴリズムの勉強をしているのですが、読んでいる書籍に
線形探索は「番兵」を用いた実装の工夫で定数倍の高速化が期待できます
(引用元: 渡部有隆 - プログラミングコンテスト攻略のためのアルゴリズムとデータ構造 (2015))
という記述があり実際に試してみることにしました。
1000個の異なる正の整数からなるリストの中に、無作為に選ばれたある整数が含まれるかどうか、また含まれる場合は何番目かを返す関数を2つ用意します。
1つは純粋な線形探索、もう一方は番兵付きです。
timeitを用いて100万回試したときのそれぞれの処理時間の平均を計測したのですが、予想に反して番兵アルゴリズムの方が遅いという結果になりました。
linear search: 5.852486592900002e-05
sentinel search: 7.166582232300002e-05
これがどうしてなのかが良く分かりません。
私のコードに問題があるのか、あるいはPythonではif判定を1000回行うよりもlist.append(),list.pop()を1度ずつ行う方が重いのでしょうか?
コード
Python
1from random import randint, sample 2from timeit import timeit 3 4# list of random unique integers 5lst = sample(range(1, 1001), 1000) 6 7# Linear search 8def lin_search(tgt: int, lst: list): 9 for i in range(len(lst)): 10 if lst[i] == tgt: 11 return i + 1 12 else: 13 return -1 14 15 16# Linear search with sentinel 17def lin_sentinel(tgt: int, lst: list): 18 lst.append(tgt) 19 i = 0 20 while lst[i] != tgt: 21 i += 1 22 lst.pop() 23 if i < len(lst): 24 return i + 1 25 else: 26 return -1 27 28 29loop = 1000000 30res_1 = timeit("lin_search(randint(1, 2001), lst)", globals=globals(), number=loop) 31res_2 = timeit("lin_sentinel(randint(1, 2001), lst)", globals=globals(), number=loop) 32print(f"linear search: {res_1 / loop}") 33print(f"sentinel search: {res_2 / loop}") 34 35> linear search: 5.852486592900002e-05 36> sentinel search: 7.166582232300002e-05

回答2件
あなたの回答
tips
プレビュー