Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的二进制搜索(二分法)_Python_Binary Search_Bisection - Fatal编程技术网

Python中的二进制搜索(二分法)

Python中的二进制搜索(二分法),python,binary-search,bisection,Python,Binary Search,Bisection,是否有一个库函数可以对列表/元组执行二进制搜索,如果找到,则返回项的位置;如果没有,则返回“False”(-1,None,等等) 我发现函数在中左/右对分,但即使该项不在列表中,它们仍然返回一个位置。这对于它们的预期用途来说是非常好的,但是我只想知道列表中是否有一个项目(不想插入任何内容) 我想使用对分_left,然后检查该位置的项目是否等于我正在搜索的项目,但这似乎很麻烦(我还需要做边界检查,检查数字是否可以大于列表中的最大数字)。如果有更好的方法,我想知道 编辑以澄清我需要它的原因:我知道字

是否有一个库函数可以对列表/元组执行二进制搜索,如果找到,则返回项的位置;如果没有,则返回“False”(-1,None,等等)

我发现函数在中左/右对分,但即使该项不在列表中,它们仍然返回一个位置。这对于它们的预期用途来说是非常好的,但是我只想知道列表中是否有一个项目(不想插入任何内容)

我想使用
对分_left
,然后检查该位置的项目是否等于我正在搜索的项目,但这似乎很麻烦(我还需要做边界检查,检查数字是否可以大于列表中的最大数字)。如果有更好的方法,我想知道

编辑以澄清我需要它的原因:我知道字典非常适合这样做,但我正试图尽可能降低内存消耗。我的预期用途是一种双向查找表。表中有一个值列表,我需要能够根据它们的索引访问这些值。我还希望能够找到某个特定值的索引,如果该值不在列表中,则不需要

为此使用字典是最快的方法,但会(大约)使内存需求增加一倍


我问这个问题是因为我可能忽略了Python库中的某些内容。似乎我必须按照Moe的建议编写自己的代码。

为什么不看看左/右对分的代码,并根据您的目的进行调整

像这样:

def二进制搜索(a,x,lo=0,hi=None):
如果hi为无:
hi=len(a)
当lox:
高=中
其他:
中途返回
返回-1

如果您只想查看它是否存在,请尝试将列表转换为dict:

# Generate a list
l = [n*n for n in range(1000)]

# Convert to dict - doesn't matter what you map values to
d = dict((x, 1) for x in l)

count = 0
for n in range(1000000):
    # Compare with "if n in l"
    if n in d:
        count += 1

在我的机器上,“if n in l”花了37秒,“if n in d”花了0.4秒。

这有点离题(因为Moe对OP的问题的回答似乎完整),但可能值得一看整个过程从头到尾的复杂性。如果您将内容存储在一个排序列表中(二进制搜索将有助于此),然后只是检查是否存在,则会导致(最坏情况,除非指定):

已排序列表

  • O(n log n)最初创建列表(如果它是未排序的数据。O(n),如果它已排序)
  • O(logn)查找(这是二进制搜索部分)
  • O(n)插入/删除(可能是O(1)或O(对数n)的平均情况,取决于您的模式)
然而,如果你有一个

  • O(n)创建
  • O(1)查找
  • O(1)插入/删除

一个排序列表真正得到的是“下一个”、“上一个”和“范围”(包括插入或删除范围),它们是O(1)或O(| range |),给定一个起始索引。如果您不经常使用这些类型的操作,那么总体而言,将其存储为集合并进行显示排序可能会更好。在python中产生的额外开销很少

除非存储的对象非常小,否则使用dict不会让内存使用量翻倍,因为这些值只是指向实际对象的指针:

>>> a = 'foo'
>>> b = [a]
>>> c = [a]
>>> b[0] is c[0]
True
在该示例中,“foo”只存储一次。这对你有影响吗?我们到底讨论了多少个项目?

最简单的方法是使用并检查一个位置,看看该项目是否存在:

def binary_search(a,x,lo=0,hi=-1):
    i = bisect(a,x,lo,hi)
    if i == 0:
        return -1
    elif a[i-1] == x:
        return i-1
    else:
        return -1

bisect_left
查找第一个位置
p
,在该位置可以将元素插入给定的排序范围,同时保持排序顺序。如果范围内存在
x
,则这将是
x
的位置。如果
p
超过结束位置,则未找到
x
。否则,我们可以测试是否存在
x
,以查看是否找到了
x

从对分导入左对分
def二进制搜索(a、x、lo=0、hi=None):
如果hi为无:hi=len(a)
pos=对分_左(a、x、lo、hi)#查找插入位置
返回pos如果pos!=嗨,a[pos]==x else-1#不要走到尽头

值得一提的是,对分文档现在提供了搜索示例:


(例如,提高ValueError而不是返回-1或None更像python–list.index()这样做。当然,您可以根据需要调整示例。)

此代码以递归方式处理整数列表。查找最简单的案例场景,即:列表长度小于2。这意味着答案已经存在,并执行测试以检查正确答案。 如果不是,则设置中间值并测试其是否正确;如果不是,则通过再次调用函数执行平分,但通过向左或向右移动将中间值设置为上限或下限

def binary_search(intList, intValue, lowValue, highValue): if(highValue - lowValue) < 2: return intList[lowValue] == intValue or intList[highValue] == intValue middleValue = lowValue + ((highValue - lowValue)/2) if intList[middleValue] == intValue: return True if intList[middleValue] > intValue: return binary_search(intList, intValue, lowValue, middleValue - 1) return binary_search(intList, intValue, middleValue + 1, highValue) def二进制搜索(intList、intValue、lowValue、highValue): 如果(高值-低值)< 2: 返回intList[lowValue]==intValue或intList[highValue]==intValue 中间值=低值+((高值-低值)/2) 如果intList[middleValue]==intValue: 返回真值 如果intList[middleValue]>intValue: 返回二进制搜索(intList、intValue、lowValue、middleValue-1) 返回二进制搜索(intList、intValue、middleValue+1、highValue)
“”
仅在将您的职位设置为全局时使用
'''
位置#设置全局
def bst(数组,标记):#只需传递数组和目标
全球地位
低=0
高=透镜(阵列)

低查看维基百科上的示例

def二进制搜索(a,键,imin=0,imax=None):
如果imax为无:
#如果未设置最大金额,则获取总金额
imax=len(a)-1
而imin键:
#将最大索引更改为搜索
'''
Only used if set your position as global
'''
position #set global 

def bst(array,taget): # just pass the array and target
        global position
        low = 0
        high = len(array)
    while low <= high:
        mid = (lo+hi)//2
        if a[mid] == target:
            position = mid
            return -1
        elif a[mid] < target: 
            high = mid+1
        else:
            low = mid-1
    return -1
def binary_search(a, key, imin=0, imax=None):
    if imax is None:
        # if max amount not set, get the total
        imax = len(a) - 1

    while imin <= imax:
        # calculate the midpoint
        mid = (imin + imax)//2
        midval = a[mid]

        # determine which subarray to search
        if midval < key:
            # change min index to search upper subarray
            imin = mid + 1
        elif midval > key:
            # change max index to search lower subarray
            imax = mid - 1
        else:
            # return index number 
            return mid
    raise ValueError
def binary_search(L, x):
    i = bisect.bisect_left(L, x)
    if i == len(L) or L[i] != x:
        return -1
    return i
import bisect

class sqrt_array(object):
    def __init__(self, digits):
        self.precision = float(10**(digits))
    def __getitem__(self, key):
        return (key/self.precision)**2.0

sa = sqrt_array(4)

# "search" in the range of 0 to 10 with a "precision" of 0.0001
index = bisect.bisect_left(sa, 7, 0, 10*10**4)
print 7**0.5
print index/(10**4.0)
>>> import bisect
>>> names = ['bender', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> bisect.bisect_left(names, 'fry')
1
>>> keyword = 'fry'
>>> x = bisect.bisect_left(names, keyword)
>>> names[x] == keyword
True
>>> keyword = 'arnie'
>>> x = bisect.bisect_left(names, keyword)
>>> names[x] == keyword
False
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
def index(a, x):
    'Locate the leftmost value exactly equal to x'
    i = bisect_left(a, x)
    if i != len(a) and a[i] == x:
        return i
    raise ValueError
def index(a, x):
    'Locate the leftmost value exactly equal to x'
    i = bisect_left(a, x)
    if i != len(a) and a[i] == x:
        return i
    return -1
def binary(s,p,q,find):
    if find==s[(p+q)/2]:
        return (p+q)/2
    elif p==q-1 or p==q:
        if find==s[q]:
            return q
        else:
            return -1
    elif find < s[(p+q)/2]:
        return binary(s,p,(p+q)/2,find)
    elif find > s[(p+q)/2]:
        return binary(s,(p+q)/2+1,q,find)
def binsearch(t, key, low = 0, high = len(t) - 1):
    # bisecting the range
    while low < high:
        mid = (low + high)//2
        if t[mid] < key:
            low = mid + 1
        else:
            high = mid
    # at this point 'low' should point at the place
    # where the value of 'key' is possibly stored.
    return low if t[low] == key else -1
def binary_search(values, key, lo=0, hi=None, length=None, cmp=None):
    """
    This is a binary search function which search for given key in values.
    This is very generic since values and key can be of different type.
    If they are of different type then caller must specify `cmp` function to
    perform a comparison between key and values' item.
    :param values:  List of items in which key has to be search
    :param key: search key
    :param lo: start index to begin search
    :param hi: end index where search will be performed
    :param length: length of values
    :param cmp: a comparator function which can be used to compare key and values
    :return: -1 if key is not found else index
    """
    assert type(values[0]) == type(key) or cmp, "can't be compared"
    assert not (hi and length), "`hi`, `length` both can't be specified at the same time"

    lo = lo
    if not lo:
        lo = 0
    if hi:
        hi = hi
    elif length:
        hi = length - 1
    else:
        hi = len(values) - 1

    while lo <= hi:
        mid = lo + (hi - lo) // 2
        if not cmp:
            if values[mid] == key:
                return mid
            if values[mid] < key:
                lo = mid + 1
            else:
                hi = mid - 1
        else:
            val = cmp(values[mid], key)
            # 0 -> a == b
            # > 0 -> a > b
            # < 0 -> a < b
            if val == 0:
                return mid
            if val < 0:
                lo = mid + 1
            else:
                hi = mid - 1
    return -1
def binary_search_length_of_a_list(single_method_list):
    index = 0
    first = 0
    last = 1

    while True:
        mid = ((first + last) // 2)
        if not single_method_list.get(index):
            break
        index = mid + 1
        first = index
        last = index + 1
    return mid
// List - values inside list
// searchItem - Item to search
// size - Size of list
// upperBound - higher index of list
// lowerBound - lower index of list
def binarySearch(list, searchItem, size, upperBound, lowerBound):
        print(list)
        print(upperBound)
        print(lowerBound)
        mid = ((upperBound + lowerBound)) // 2
        print(mid)
        if int(list[int(mid)]) == value:
               return "value exist"
        elif int(list[int(mid)]) < value:
             return searchItem(list, value, size, upperBound, mid + 1)
        elif int(list[int(mid)]) > value:
               return searchItem(list, value, size, mid - 1, lowerBound)
list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
searchItem = 1        
print(searchItem(list[0], item, len(list[0]) -1, len(list[0]) - 1, 0))
#Code
from bisect import bisect_left
names=["Adam","Donny","Jalan","Zach","Zayed"]
search=""
lenNames = len(names)
while search !="none":
    search =input("Enter name to search for or 'none' to terminate program:")
    if search == "none":
        break
    i = bisect_left(names,search)
    print(i) # show index returned by Python bisect_left
    if i < (lenNames) and names[i] == search:
        print(names[i],"found") #return True - if function
    else:
        print(search,"not found") #return False – if function
##Exhaustive test cases:
##Enter name to search for or 'none' to terminate program:Zayed
##4
##Zayed found
##Enter name to search for or 'none' to terminate program:Zach
##3
##Zach found
##Enter name to search for or 'none' to terminate program:Jalan
##2
##Jalan found
##Enter name to search for or 'none' to terminate program:Donny
##1
##Donny found
##Enter name to search for or 'none' to terminate program:Adam
##0
##Adam found
##Enter name to search for or 'none' to terminate program:Abie
##0
##Abie not found
##Enter name to search for or 'none' to terminate program:Carla
##1
##Carla not found
##Enter name to search for or 'none' to terminate program:Ed
##2
##Ed not found
##Enter name to search for or 'none' to terminate program:Roger
##3
##Roger not found
##Enter name to search for or 'none' to terminate program:Zap
##4
##Zap not found
##Enter name to search for or 'none' to terminate program:Zyss
##5
##Zyss not found
def bisectLeft(a, t):
    lo = 0
    hi = len(a) - 1
    ans = None
    # print("------lower------")
    # print(a, t)
    while lo <= hi:
        mid = (lo + hi) // 2
        # print(a[lo:mid], [a[mid]], a[mid:hi])
        if a[mid] < t:
            lo = mid + 1
        elif a[mid] > t:
            hi = mid - 1
        elif a[mid] == t:
            if mid == 0: return 0
            if a[mid-1] != t: return mid
            hi = mid - 1
            
    return ans

def bisectRight(a, t):
    lo = 0
    hi = len(a) - 1
    ans = None
    # print("------upper------")
    # print(a, t)
    while lo <= hi:
        mid = (lo + hi) // 2
        # print(a[lo:mid], [a[mid]], a[mid:hi])
        if a[mid] == t:
            ans = mid
        if a[mid] <= t:
            lo = mid + 1
        else:
            hi = mid - 1
    return ans