Python二进制搜索实现中的边界搜索项

时间:2019-10-02 06:06:52

标签: python python-3.x binary-search

我已经以不同的方式在Python中实现了二进制搜索,并且正在针对排序列表进行测试。当搜索项超出列表的最小值和最大值的范围时,迭代解决方案将失败。

我已经做了一些初步的测试和调试。我无法理解实施中的问题。

def bisect_search_itr(L, e):
  low = 0
  high = len(L)
  mid_index = (low + high) // 2
  while low <= high:
    if L[mid_index] == e:
      return True
    else:
      if e > L[mid_index]:
        low = mid_index
      else:
        high = mid_index
    mid_index = (low + high) // 2
  return False

def bisect_search_rec(L, e):
  if L == []:
    return False
  elif len(L) == 1:
    return L[0] == e
  else:
    half = len(L) // 2
    if L[half] > e:
      return bisect_search_rec(L[:half], e)
    else:
      return bisect_search_rec(L[half:], e)

def bisect_search_rec_with_bounds(e, m, n):
  if m == n:
    return L[m] == e
  else:
    half = m+n//2
    if L[half] == e:
      return True
    else:
      if e < L[half]:
        return bisect_search_rec_with_bounds(e, m, half)
      else: 
        return bisect_search_rec_with_bounds(e, half, n)

# Test case
L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
x = 17

print(bisect_search_itr(L, x))
print(bisect_search_rec(L, x))
print(bisect_search_rec_with_bounds(x, 0, len(L) - 1))

递归实现的效果很好,但对于迭代实现,它会陷入无限循环。

2 个答案:

答案 0 :(得分:0)

错误位于Nested Loop (cost=0.72..162190.37 rows=1647921 width=187) (actual time=2.589..18590.362 rows=7775 loops=1) Buffers: shared hit=44030111 read=3348 I/O Timings: read=20.984 -> Index Scan using data_timestamp_machine_id_name_unique on data pd (cost=0.43..20237.60 rows=1730 width=81) (actual time=0.055..50.357 rows=7713 loops=1) Index Cond: (("timestamp" > '2019-09-15 22:00:00-07'::timestamp with time zone) AND ("timestamp" <= '2019-09-22 21:59:59.999-07'::timestamp with time zone) AND (machine_id = 19) AND ((name)::text = 'weight'::text)) Buffers: shared hit=5132 read=3216 I/O Timings: read=20.591 -> Index Scan using orders_machine_id_idx on orders o (cost=0.29..72.52 rows=953 width=106) (actual time=2.401..2.401 rows=1 loops=7713) Index Cond: ((machine_id = 19) AND (pd."timestamp" > start_time)) Filter: (pd."timestamp" <= COALESCE(end_time, now())) Rows Removed by Filter: 7108 Buffers: shared hit=44024979 read=132 I/O Timings: read=0.393 Planning Time: 0.191 ms Execution Time: 18591.568 ms 行中,并且该循环的唯一出口是通过while low <= high:。在示例数据中,目标元素不在列表中。经过几次迭代后,low,high和mid_index都将位于列表的最高位置。

根据您要实现的方式,您可以返回最接近的数字(15),或者如果L[mid_index] == elow相等则抛出错误。

答案 1 :(得分:0)

调试此问题非常容易。只需附加一个调试器(或使用print语句),即可查看导致无限循环的根本原因是在某个点之后(lowhigh彼此接近时),循环中没有任何内容变化。

让我们看一个非常简化的示例:L = [1, 2]x = 5。在这种情况下,low = 1high = 2mid_index = 1。在循环内部,您会看到该元素大于mid,因此将low = mid_index设置为1,最后将mid_index设置为1。因此,没有任何变化。您实际上并没有增加low,也没有mid_index,也没有无限循环。对于任何不包含L的{​​{1}},经过足够的迭代,您会在循环内找到这种确切的情况。

要解决此问题,请确保对于每次迭代xlow都进行更改。例如,由于您已经检查了high元素是否不是您要查找的元素,因此将mid_index设置为low是安全的。

相关问题