Search code examples
pythonbinary-search

Why my binary search function doesn't stop when the element isn't in the list?


I have the following binary search function:

def in_bisect(sorted_list, target):

    temp = sorted_list[:]
    low = 0 
    mid = (len(temp)-1) // 2 
    high = len(temp)-1 
    count = 0
    
    if target > temp[high] or target < temp[low]:
        return False
    
    while True:
        mid = len(temp) // 2 
        count += 1
        if target == temp[mid]:
            print("Target found in %d steps " % count)
            return True

        elif target > temp[mid]:  
            low = mid             
            temp = temp[low:]
        
        elif target < temp[mid]: 
            high = mid           
            temp = temp[:high]

    
    return False

It works fine when I look for an element on the given list of words. However, when I test a word that isn't on the list the loop goes to infinite!!!

I have tested it with a list of 113k+ alphabetically sorted words, and it is very efficient (or that what I'd like think at least) it finds the target in 17 steps maximum.

This is a test I did :

if __name__ == '__main__':
    fin = open('words.txt')
    a = []
    for line in fin:
        a.append(line.strip())
    print(in_bisect(a,'longsome'))

'longsome' is a word in words.txt file, if I change it to let's say 'blahblah' the loop goes for ever.

I would like it to return False immediately if there is no match. Also, any improvement suggestions along the way is appreciated, thanks.


Solution

  • There was no way for the while loop to break, so until we run out of the range to search for, we go on, otherwise, we break. Also, low = mid + 1 was required as otherwise the list size won't reduce properly. Same for high.

    def in_bisect(sorted_list, target):
    
        temp = sorted_list[:]
        low = 0 
        mid = (len(temp)-1) // 2 
        high = len(temp)-1 
        count = 0
        
        if target > temp[high] or target < temp[low]:
            return False
        
        while True:
            if len (temp) == 0:
                break
            mid = len(temp) // 2
            count += 1
            if target == temp[mid]:
                print("Target found in %d steps " % count)
                return True
    
            elif target > temp[mid]:  
                low = mid + 1             
                temp = temp[low:]
            
            elif target < temp[mid]: 
                high = mid - 1           
                temp = temp[:high + 1]
    
        
        return False