我已经以不同的方式在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))
递归实现的效果很好,但对于迭代实现,它会陷入无限循环。
答案 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] == e
和low
相等则抛出错误。
答案 1 :(得分:0)
调试此问题非常容易。只需附加一个调试器(或使用print语句),即可查看导致无限循环的根本原因是在某个点之后(low
和high
彼此接近时),循环中没有任何内容变化。
让我们看一个非常简化的示例:L = [1, 2]
,x = 5
。在这种情况下,low = 1
,high = 2
,mid_index = 1
。在循环内部,您会看到该元素大于mid,因此将low = mid_index
设置为1,最后将mid_index
设置为1。因此,没有任何变化。您实际上并没有增加low
,也没有mid_index
,也没有无限循环。对于任何不包含L
的{{1}},经过足够的迭代,您会在循环内找到这种确切的情况。
要解决此问题,请确保对于每次迭代x
或low
都进行更改。例如,由于您已经检查了high
元素是否不是您要查找的元素,因此将mid_index
设置为low
是安全的。