पाइथन में बाइनरी सर्च (बिसनेस)


177

क्या कोई लाइब्रेरी फ़ंक्शन है जो किसी सूची / टपल पर बाइनरी खोज करता है और यदि पाया गया है और 'गलत' (-1, कोई नहीं, आदि) आइटम की स्थिति वापस करता है तो नहीं?

मुझे बाइसेक्ट मॉड्यूल में फ़ंक्शंस bisect_left / right मिला , लेकिन वे अभी भी एक पोज़िशन वापस करते हैं, भले ही आइटम सूची में न हो। यह उनके इच्छित उपयोग के लिए पूरी तरह से ठीक है, लेकिन मैं सिर्फ यह जानना चाहता हूं कि कोई सूची में है या नहीं (कुछ भी सम्मिलित नहीं करना चाहते हैं)।

मैंने उपयोग करने bisect_leftऔर फिर जांचने के बारे में सोचा कि क्या उस स्थिति में आइटम जो मैं खोज रहा हूं उसके बराबर है, लेकिन यह बोझिल लगता है (और मुझे यह भी जांचने की आवश्यकता है कि क्या संख्या मेरी सूची में सबसे बड़ी संख्या से अधिक हो सकती है)। अगर वहाँ एक अच्छा तरीका है मैं इसके बारे में जानना चाहते हैं।

संपादित करें यह स्पष्ट करने के लिए कि मुझे इसके लिए क्या चाहिए: मुझे पता है कि इसके लिए एक शब्दकोश बहुत अच्छी तरह से अनुकूल होगा, लेकिन मैं स्मृति खपत को यथासंभव कम रखने की कोशिश कर रहा हूं। मेरा इच्छित उपयोग एक तरह का डबल-लुक-अप टेबल होगा। मेरे पास तालिका में मूल्यों की एक सूची है और मुझे उनके सूचकांक के आधार पर मूल्यों तक पहुंचने में सक्षम होने की आवश्यकता है। और यह भी कि मैं किसी विशेष मूल्य के सूचकांक को खोजने में सक्षम होना चाहता हूं या यदि कोई मूल्य सूची में नहीं है।

इसके लिए एक शब्दकोश का उपयोग करना सबसे तेज़ तरीका होगा, लेकिन (लगभग) मेमोरी आवश्यकताओं को दोगुना कर देगा।

मैं यह सोच कर यह सवाल पूछ रहा था कि मैंने पायथन पुस्तकालयों में कुछ अनदेखी की होगी। ऐसा लगता है कि मुझे अपना कोड लिखना होगा, जैसा कि Moe ने सुझाव दिया था।


1
वह क्या है जिसे आप पूरा करने की कोशिश कर रहे हैं? यदि मान अद्वितीय हैं, तो एक सेट का उपयोग करने पर विचार करें और "यदि सेट में मान: कुछ"।
कर्क स्ट्रुसर

इसके लायक होने के लिए, "-1" को सच माना जाता है; "0" झूठी होगी।
ग्लिफ ऑक्ट

3
मैंने -1 का उल्लेख किया है क्योंकि एक फ़ंक्शन जो सरणी में खोज की गई वस्तु के सूचकांक को वापस करता है, 0 पहले से ही वापस आ सकता है -1 यदि आइटम नहीं मिला है तो वापस लौटा है (खोज को प्रतिस्थापित करने के समान)।
rslite 11

3
यदि आप सुन्न का उपयोग करते हैं, np.searchsortedतो उपयोगी है। docs.scipy.org/doc/numpy/reference/generated/…
रोमन

जवाबों:


238
from bisect import bisect_left

def binary_search(a, x, lo=0, hi=None):  # can't use a to specify default for hi
    hi = hi if hi is not None else len(a)  # hi defaults to len(a)   
    pos = bisect_left(a, x, lo, hi)  # find insertion position
    return pos if pos != hi and a[pos] == x else -1  # don't walk off the end

10
@volcano तो सामान्य रूप से binsearch करता है।
cubuspl42

4
@ टॉम्सवीरी आपकी तरह सरल नहीं है, लेकिन सही है और अभी भी एक सुधार है:if hi is None: hi = len(a)
मार्क रैनसम

अवरोही क्रम के बारे में क्या?
परीक्षित चालके '

2
क्या आप कोड के बाहर कुछ स्पष्टीकरण जोड़ सकते हैं? यहां मानक बदल गए हैं।
एसएस ऐनी

54

क्यों नहीं bisect_left / right के लिए कोड देखें और अपने उद्देश्य के अनुसार इसे अनुकूलित करें।

इस तरह:

def binary_search(a, x, lo=0, hi=None):
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        midval = a[mid]
        if midval < x:
            lo = mid+1
        elif midval > x: 
            hi = mid
        else:
            return mid
    return -1

29
मैं मूल रूप से यह 1'ed हूं, लेकिन अब मैं इस निष्कर्ष पर पहुंचा हूं कि यह अच्छी बात नहीं है। यदि इस उत्तर का पालन किया जाता है, तो यह बहुत सारे कोड दोहराव का कारण बनेगा, और जैसा कि हम सभी जानते हैं, यह द्विआधारी खोज के लिए f * ck वास्तव में सरल है।
abyx

1
यह नहीं होना चाहिए hi = mid - 1में elif?
पवन प्रालक

7
@ पवेल: वे दो समान रूप हैं, जो इस बात पर निर्भर करता है कि ऊपरी बाउंड समावेशी है या अनन्य। आप बदल सकते हैं hi = midकरने के लिए hi = mid-1और hi = len(a)करने के लिए hi = len(a)-1और while lo < hi:करने के लिए while lo <= hi, और यह समतुल्य रूप सही होगा
user102008

2
ऐसा कुछ क्यों न करें: बाइनरी_सर्च (ए, एक्स, लो = 0, हाय = कोई नहीं) को परिभाषित करें: i = बीसेक्ट (ए, एक्स, लो, हाय) अगर मैं एक [i] == x और -1 के लिए क्षमा करें फ़ॉर्मेटिंग - सुनिश्चित नहीं है कि टिप्पणी में यह ठीक से कैसे किया जाए
विटाली

1
आपको इसके bisect.bisect_left()बजाय उपयोग करना चाहिए ।
एलास्टेयर

37

यह थोड़ा ऑफ-टॉपिक है (चूंकि Moe का उत्तर ओपी के प्रश्न के लिए पूर्ण लगता है), लेकिन यह आपकी संपूर्ण प्रक्रिया के लिए अंत से जटिलता को देखने के लायक हो सकता है। यदि आप किसी सॉर्ट की गई सूची में चीज़ संग्रहीत कर रहे हैं (जो बाइनरी खोज में मदद करेगा), और फिर अस्तित्व के लिए जाँच कर रहा है, तो आप कर रहे हैं (सबसे खराब स्थिति, जब तक निर्दिष्ट नहीं):

क्रमबद्ध सूची

  • O (n लॉग एन) शुरू में सूची बनाने के लिए (यदि यह बिना डेटा के है। O (n), यदि यह सॉर्ट किया गया है)
  • O (लॉग एन) लुकअप (यह बाइनरी सर्च पार्ट है)
  • O (n) सम्मिलित करें / हटाएं (आपके पैटर्न के आधार पर O (1) या O (लॉग एन) औसत मामला हो सकता है)

जबकि एक के साथ set(), आप कर रहे हैं

  • O (n) बनाना है
  • O (1) लुकअप
  • O (1) डालें / हटाएं

एक सॉर्ट की गई सूची वास्तव में आपको "अगली", "पिछली", और "पर्वतमाला" (श्रेणी सम्मिलित करने या हटाने सहित) मिलती है, जो कि O (1) या O ((श्रेणी |)) हैं, जो एक आरंभिक सूचकांक है। यदि आप अक्सर उन प्रकारों के संचालन का उपयोग नहीं कर रहे हैं, तो सेट के रूप में भंडारण कर रहे हैं, और प्रदर्शन के लिए छंटाई समग्र रूप से बेहतर सौदा हो सकती है। set()अजगर में बहुत कम अतिरिक्त ओवरहेड।


7
एक अन्य चीज़ है जो आपको क्रमबद्ध सूची मिलती है। O (n) ने ट्रैवर्सल का आदेश दिया। ओ (एन लॉग एन) के एक सेट के साथ और आप सूची में डेटा के संदर्भों को कॉपी करने के लिए समाप्त होते हैं।
सर्वव्यापी

1
आधी हकीकत! रेंज खोज से मेरा क्या मतलब है, इसका विस्तार करने के लिए धन्यवाद। Fwiw, एक पूर्ण ट्रैवर्सल मिनट, अधिकतम, जो O (k) है, जहां k = n :) के बीच एक श्रेणी क्वेरी है
ग्रेग लिंड

14

यह ध्यान देने योग्य बात हो सकती है कि अब बिस्केट डॉक्स खोज उदाहरण प्रदान करते हैं: http://docs.python.org/library/bisect.html#searching-sorted-lists

(रिटर्न -1 की बजाय राइजिंग वैल्यूऑवर। कोई भी अधिक पाइथोनिक नहीं है। उदाहरण के लिए list.index () करता है। लेकिन निश्चित रूप से आप अपनी आवश्यकताओं के लिए उदाहरणों को अनुकूलित कर सकते हैं।)


11

सबसे आसान उपयोग करने के लिए है द्विविभाजित और एक स्थिति में फिर से देखें देखने के लिए कि आइटम नहीं है:

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

2
यदि आप 'hi' मान में पास नहीं होते हैं तो अच्छा है, लेकिन कोड बारफोंस। मैं इसे इस तरह से लिखूंगा: "बाइनरी_सर्च (ए, एक्स, लो = 0, हाय = कोई नहीं): बायसेक्ट इंपोर्ट बाइसेक्ट से मैं = बाइसेक्ट (ए, एक्स, लो, हाय या लेन (ए)) रिटर्न (i) 1 अगर एक [i-1] == x और -1) "और इसे इस तरह से टेस्ट करें:" i in रेंज में (1, 20): a = j: Binary_search में आ के लिए एक = सूची (रेंज (i)) (a, aa) अगर j! = aa: print i, aa, j "
hughdbrown

8

यह मैनुअल से सही है:

http://docs.python.org/2/library/bisect.html

8.5.1। क्रमबद्ध सूचियों की खोज करना

उपरोक्त द्विभाजन () फ़ंक्शन सम्मिलन बिंदुओं को खोजने के लिए उपयोगी हैं, लेकिन आम खोज कार्यों के लिए उपयोग करने के लिए मुश्किल या अजीब हो सकते हैं। निम्नलिखित पाँच कार्य यह दिखाते हैं कि उन्हें छांटे गए सूचियों के मानक लुकअप में कैसे बदलना है:

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

6

मैं मानता हूं कि बिस्केट मॉड्यूल का उपयोग कर @ DaveAbrahams का उत्तर सही दृष्टिकोण है। उन्होंने अपने उत्तर में एक महत्वपूर्ण विवरण का उल्लेख नहीं किया।

से डॉक्स bisect.bisect_left(a, x, lo=0, hi=len(a))

द्विध्रुव मॉड्यूल को समय से पहले खोज सरणी की आवश्यकता नहीं होती है। आप bisect.bisect_leftइसके बजाय डिफॉल्ट का उपयोग करके एंडपॉइंट्स को प्रस्तुत कर सकते हैं 0और len(a)

मेरे उपयोग के लिए और भी अधिक महत्वपूर्ण है, एक मूल्य X की तलाश में जैसे कि किसी दिए गए फ़ंक्शन की त्रुटि कम से कम हो। ऐसा करने के लिए, मुझे bisect_left के एल्गोरिथ्म को इसके बजाय मेरी संगणना को कॉल करने का एक तरीका चाहिए। यह वास्तव में सरल है।

बस के __getitem__रूप में परिभाषित करता है कि एक वस्तु प्रदान करते हैंa

उदाहरण के लिए, हम मनमाने ढंग से परिशुद्धता के साथ एक वर्गमूल खोजने के लिए बाइसेक्ट एल्गोरिथ्म का उपयोग कर सकते हैं!

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)

यह साफ नहीं है। इसके लिए उपयोग scipy.optimizeकरें।
नील जी

4

यदि आप यह देखना चाहते हैं कि क्या यह मौजूद है, तो सूची को एक तानाशाही में बदलने की कोशिश करें:

# 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

मेरी मशीन पर, "अगर n में l" में 37 सेकंड लगे, जबकि "if n में d" ने 0.4 सेकंड का समय लिया।


2
यह हमेशा कुछ कारणों के लिए एक अच्छा विकल्प नहीं है: 1) dicts / सेट अधिक मेमोरी लेते हैं। 2) यदि उसके पास सूची में ज्यादा नहीं है, तो एक द्विआधारी खोज तेज हो सकती है। 3) सूची को एक तानाशाह में परिवर्तित करना एक O (n) ऑपरेशन है जबकि एक द्विआधारी खोज O (लॉग एन) है।
जेसन बेकर

3
एक FYI के रूप में, अजगर सूचियों की तुलना में अजगर में "सेट" ओवरहेड बहुत कम है। और वे लुकअप के लिए बेहद तेज़ हैं। जहां बाइनरी सर्च वास्तव में एक्सेल की तलाश में है।
ग्रीग लिंड

सूची को परिवर्तित करना O (n) हो सकता है, लेकिन सूची में मौजूद डेटा को क्रमबद्ध करना, जो आपको बाइनरी सर्च करने से पहले करना होगा, वह बदतर है। डेटा कहाँ से आ रहा है, आप संभवतः इसे एक डिक्शनरी में डाल सकते हैं जैसे आप जाते हैं। मैं मानता हूं कि स्मृति एक मुद्दा हो सकता है।
मार्क बेकर

4

यह एक है:

  • पुनरावर्ती नहीं (जो इसे सबसे पुनरावर्ती दृष्टिकोणों की तुलना में अधिक स्मृति-कुशल बनाता है )
  • वास्तव में काम कर रहा है
  • उपवास के बाद से यह बिना किसी अनावश्यक और शर्तों के चलता है
  • एक गणितीय दावे के आधार पर कि (निम्न + उच्च) / 2 का तल हमेशा उच्च की तुलना में छोटा होता है जहाँ निम्न निम्न सीमा होती है और उच्च ऊपरी सीमा होती है।

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

क्या आप परीक्षण के मामलों को साझा कर सकते हैं?
लाइफबैलेंस

2

डेव अब्राहम का समाधान अच्छा है। हालाँकि मैंने इसे न्यूनतम किया होगा:

def binary_search(L, x):
    i = bisect.bisect_left(L, x)
    if i == len(L) or L[i] != x:
        return -1
    return i

2

जबकि पायथन में कोई स्पष्ट बाइनरी खोज एल्गोरिथ्म नहीं है, एक मॉड्यूल है - bisect- एक द्विआधारी खोज का उपयोग करके सॉर्ट की गई सूची में एक तत्व के लिए सम्मिलन बिंदु खोजने के लिए डिज़ाइन किया गया है। यह द्विआधारी खोज करने में "छल" हो सकता है। इसका सबसे बड़ा फायदा यह है कि अधिकांश लाइब्रेरी कोड का एक ही फायदा है - यह उच्च प्रदर्शन, अच्छी तरह से परीक्षण किया गया है और बस काम करता है (विशेष रूप से बाइनरी खोजों को सफलतापूर्वक लागू करना काफी मुश्किल हो सकता है - खासकर अगर बढ़त के मामलों को ध्यान से नहीं माना जाता है)।

मूल प्रकार

बुनियादी प्रकारों जैसे स्ट्रिंग्स या किट्स के लिए यह बहुत आसान है - आप सभी की जरूरत bisectमॉड्यूल और एक क्रमबद्ध सूची है:

>>> 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']

यह कम से कम पायथन 2.7 -> 3.3 में काम करना चाहिए


1

जब तक आपके द्वारा संग्रहीत की जा रही वस्तुएं वास्तव में छोटी न हों, तब तक एक तानाशाही का उपयोग करना आपकी स्मृति के उपयोग को दोगुना नहीं करेगा, क्योंकि मूल्य केवल वास्तविक वस्तुओं के संकेत हैं:

>>> a = 'foo'
>>> b = [a]
>>> c = [a]
>>> b[0] is c[0]
True

उस उदाहरण में, 'फू' को केवल एक बार संग्रहीत किया जाता है। क्या इससे आपको फर्क पड़ता है? और वास्तव में हम कितने आइटमों के बारे में बात कर रहे हैं?


यह संख्या और उनमें से बहुत सारे के बारे में है :) मैं एक सरणी का उपयोग लगभग कंप्यूटर मेमोरी जितना बड़ा करना चाहूंगा। मुझे पता है कि मेरी समस्या का आधार गलत हो सकता है, लेकिन मैं एक द्विआधारी खोज पद्धति की कमी के बारे में उत्सुक था।
rslite 11

1
आपके पास यहां "वास्तव में छोटे" के रूप में अर्हता प्राप्त करने के लिए एक छोटी वस्तु पर्याप्त नहीं हो सकती है। एक ऑब्जेक्ट में न्यूनतम 3 शब्द होंगे (प्रकार, रीफ़ाउंट, पेलोड), जबकि एक सूची में 1 शब्द, एक सेट में 1 शब्द और 2 शब्दों के साथ एक तानाशाही जोड़ी जाती है। तीनों (सूची / सेट / तानाशाह) कुछ फैशन में भी प्रचार करते हैं, जो एक और गुणक है, लेकिन फिर भी बात करने के लिए पर्याप्त नहीं है।
रामफोरिनेकस

1

यह कोड पुनरावर्ती तरीके से पूर्णांक सूचियों के साथ काम करता है। सबसे सरल स्थिति परिदृश्य के लिए, जो है: सूची की लंबाई 2. से कम है। इसका मतलब है कि उत्तर पहले से ही है और सही उत्तर की जांच के लिए एक परीक्षण किया जाता है। यदि नहीं, तो एक मध्य मान सेट किया जाता है और सही होने के लिए परीक्षण किया जाता है, यदि नहीं तो फिर से फ़ंक्शन को कॉल करके बाइसेक्शन नहीं किया जाता है, लेकिन मध्य मान को ऊपरी या निचली सीमा के रूप में सेट करके, इसे बाईं या दाईं ओर स्थानांतरित करके।

डीईएन बाइनरी_सर्च (इंटलिस्ट, इंटल्यू, लोवैल्यू, हाईवैल्यू))
    अगर (उच्चावच - निम्नवत्) <2:
        intList लौटाएं [lowValue] == intValue या intList [highValue] == intValue
    मिडलव्यू = लोवल्यू + ((हाईवैल्यू - लोवैल्यू) / 2)
    यदि intList [मिडिलव्यू] == intValue:
        सच लौटाओ
    अगर intList [मिडिलव्यू]> इंटवैल्यू:
        बाइनरी_सर्च (इंटलिस्ट, इंटलव्यू, लोवैल्यू, मिडलव्यू - 1) लौटाएं
   बाइनरी_सर्च (intList, intValue, midValue + 1, highValue) लौटाएं

1

विकिपीडिया http://en.wikipedia.org/wiki/Binary_search_algorithm पर उदाहरण देखें

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

0
'''
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

मुझे लगता है कि यह बहुत बेहतर और प्रभावी है। कृप्या मुझे सही करें :) । धन्यवाद


0
  • s एक सूची है।
  • binary(s, 0, len(s) - 1, find) प्रारंभिक कॉल है।
  • फंक्शन क्वेरिड आइटम का एक इंडेक्स देता है। यदि ऐसी कोई वस्तु नहीं है, तो यह वापस आ जाती है -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)

0
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

0

द्विआधारी खोज :

// 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))

0

मुझे अजगर में द्विआधारी खोज की आवश्यकता थी और Django मॉडल के लिए सामान्य। Django के मॉडल में, एक मॉडल में दूसरे मॉडल के लिए विदेशी कुंजी हो सकती है और मैं पुनर्प्राप्त मॉडल ऑब्जेक्ट पर कुछ खोज करना चाहता था। मैंने निम्नलिखित फ़ंक्शन लिखा है आप इसका उपयोग कर सकते हैं।

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

0

इसके बाद के संस्करण, लेकिन मैं एक साधारण नहीं देखा है कई अच्छे समाधान (KISS इसे सरल (क्योंकि मैं कर रहा हूँ) अजगर की बेवकूफ प्रयोग में / एक द्विआधारी खोज करने के लिए सामान्य द्विविभाजित समारोह बनाया रखने के लिए। द्विविभाजित समारोह के आसपास कोड का एक सा के साथ, मुझे लगता है कि मेरे पास एक उदाहरण है जहां मैंने नामों के एक छोटे से स्ट्रिंग सरणी के लिए सभी मामलों का परीक्षण किया है। ऊपर दिए गए कुछ समाधानों ने यह कहा / समझा, लेकिन उम्मीद है कि नीचे दिया गया सरल कोड किसी को भी भ्रमित करने में मदद करेगा जैसे मैं था।

पायथन बिसेक्ट का उपयोग यह इंगित करने के लिए किया जाता है कि किसी नए मान / खोज आइटम को एक सॉर्ट की गई सूची में कहां डाला जाए। नीचे दिया गया कोड, जो bisect_left का उपयोग करता है, जो हिट के सूचकांक को वापस लौटाएगा यदि सूची / सरणी में खोज आइटम पाया जाता है (नोट bisect और bisect_right हिट के बाद तत्व के सूचकांक को वापस करेगा या सम्मिलन बिंदु के रूप में मिलान करेगा) यदि नहीं मिला , bisect_left सॉर्ट की गई सूची में अगले आइटम पर एक इंडेक्स लौटाएगा जो खोज मूल्य = = नहीं होगा। एकमात्र अन्य मामला यह है कि खोज आइटम उस सूची के अंत में जाएगा जहां सूचकांक वापस आया सूची / सरणी के अंत से परे होगा, और जो पायथन द्वारा "और" लॉजिक हैंडल के साथ प्रारंभिक निकास से नीचे कोड में है। (पहली शर्त झूठी अजगर बाद की स्थितियों की जांच नहीं करता है)

#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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.