পাইথনে বাইনারি অনুসন্ধান (দ্বিখণ্ডিত)


177

একটি লাইব্রেরি ফাংশন রয়েছে যা তালিকায় / টুপলে বাইনারি অনুসন্ধান করে এবং যদি পাওয়া যায় তবে আইটেমের অবস্থান এবং 'মিথ্যা' (-1, কিছুই নয়) যদি না পাওয়া যায় তবে?

আমি দ্বিখণ্ডিত মডিউলে bisect_left / ডান ফাংশনগুলি পেয়েছি , তবে তারা আইটেম তালিকায় না থাকলেও তারা এখনও একটি অবস্থান ফিরে আসে। এটি তাদের উদ্দেশ্যযুক্ত ব্যবহারের জন্য পুরোপুরি ঠিক আছে, তবে আমি কেবলমাত্র একটি আইটেম তালিকায় রয়েছে কিনা তা জানতে চাই (কিছুই সন্নিবেশ করতে চাই না)।

আমি bisect_leftসেই অবস্থানটিতে থাকা আইটেমটি আমি যা অনুসন্ধান করছি তার সমান কিনা তা পরীক্ষা করার চেষ্টা করেছি, তবে এটি জটিল মনে হচ্ছে (এবং আমার তালিকার সংখ্যাটি সবচেয়ে বড় সংখ্যার চেয়ে বড় হতে পারে কি না তাও আমাকে পরীক্ষা করতে হবে)। যদি খুব ভাল পদ্ধতি থাকে তবে আমি এটি সম্পর্কে জানতে চাই।

সম্পাদনা করার জন্য আমার কী প্রয়োজন তা পরিষ্কার করতে: আমি সচেতন যে একটি অভিধান এর জন্য খুব ভাল উপযোগী হবে তবে আমি মেমরির ব্যবহার যতটা সম্ভব কম রাখার চেষ্টা করছি। আমার উদ্দেশ্য ব্যবহারটি এক ধরণের ডাবল-ওয়ে লুক-আপ টেবিল হবে। আমার কাছে টেবিলে মানগুলির একটি তালিকা রয়েছে এবং তাদের সূচকের ভিত্তিতে মানগুলি অ্যাক্সেস করতে আমার সক্ষম হওয়া দরকার। এবং আমি মানটি তালিকায় না থাকলে একটি নির্দিষ্ট মান বা কোনওটির সূচকটি সন্ধান করতে সক্ষম হতে চাই।

এর জন্য অভিধান ব্যবহার করা দ্রুততম উপায় হবে, তবে (প্রায়) মেমরির প্রয়োজনীয়তা দ্বিগুণ করবে।

আমি এই প্রশ্নটি ভাবছিলাম যে আমি পাইথন লাইব্রেরিতে কিছু উপেক্ষা করেছি something দেখে মনে হচ্ছে আমাকে নিজের কোড লিখতে হবে, মো যেমন পরামর্শ দিয়েছে।


1
আপনি কী অর্জন করতে চাইছেন? মানগুলি যদি অনন্য হয় তবে একটি সেট এবং "যদি মানটিতে সেট হয়: কিছু" ব্যবহার বিবেচনা করুন।
কર્ક স্ট্রুজার

এটির জন্য মূল্যবান, "-1" সত্য হিসাবে বিবেচিত হয়; "0" মিথ্যা হবে।
গ্লিফ

3
আমি -১ উল্লেখ করেছি কারণ অ্যারেটিতে অনুসন্ধান করা আইটেমের সূচকটি ফাংশনটি ইতিমধ্যে 0 প্রদান করতে পারে সুতরাং আইটেমটি খুঁজে পাওয়া না গেলে -1 ফিরে আসে (সাবস্ট্রিং অনুসন্ধানের অনুরূপ)।
RSSlite

3
আপনি যদি নম্পতি ব্যবহার করেন np.searchsortedতবে দরকারী। docs.scipy.org/doc/numpy/references/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
@ ভোলকানো সাধারণভাবে বিন্যাসার্ক করে।
কিউবিস্প্ল 42

4
@ টমসওয়াইরিলি আপনার মতো সহজ নয় তবে সঠিক এবং এখনও একটি উন্নতি:if hi is None: hi = len(a)
মার্ক র্যানসোম

ক্রমবর্ধমান ক্রম সম্পর্কে কি?
পরিক্ষিত চালকে

2
আপনি কোডের বাইরে কিছু ব্যাখ্যা যোগ করতে পারেন? এখানকার মান পরিবর্তন হয়েছে।
এসএস অ্যান

54

কেন বাইসেক্ট_মাম / ডান কোডটি দেখুন এবং এটি আপনার উদ্দেশ্য অনুসারে অভিযোজিত নয়।

এটার মত:

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 করেছি তবে এখন আমি এই সিদ্ধান্তে পৌঁছেছি যে এটি ভাল জিনিস নয়। যদি এই উত্তরটি অনুসরণ করা হয়, তবে এটি প্রচুর কোড ডুপ্লিকেশন ঘটায় এবং আমরা সবাই জানি, বাইনারি অনুসন্ধানে চ * সি কে আপ করা সত্যিই সহজ।
অ্যাবিক্স

1
এটা করা উচিত হবে না hi = mid - 1elif?
পাওয়ে প্র্যাক

7
@ পাউয়েł: এগুলি দুটি সমতুল্য বৈকল্পিক, উপরের সীমাটি অন্তর্ভুক্তি বা একচেটিয়া কিনা তার উপর নির্ভর করে। আপনি পরিবর্তন করতে পারেন hi = midকরতে hi = mid-1এবং hi = len(a)করতে hi = len(a)-1এবং while lo < hi:করতে while lo <= hi, এবং এটি equivalently সঠিক হবে
user102008

2
কেন এমন কিছু করবেন না: ডিফ বাইনারি_সার্চ (a, x, lo = 0, হাই = কিছুই নেই): i = দ্বিখণ্ডিত (ক, এক্স, লো, হাই) আমি ফিরে আসি যদি [i] == এক্স অন্য -1 এর জন্য দুঃখিত ফর্ম্যাটিং - কীভাবে সঠিকভাবে এটি করা উচিত তা মন্তব্য মন্তব্যে নেই
ভিটালি

1
এর bisect.bisect_left()চেয়ে আপনার ব্যবহার করা উচিত ।
অ্যালিস্টায়ার

37

এটি সামান্য অফ-টপিক (যেহেতু মো'র উত্তরটি ওপি-র প্রশ্নের সম্পূর্ণ মনে হয়েছে) তবে আপনার সম্পূর্ণ প্রক্রিয়াটি শেষ থেকে শেষ পর্যন্ত জটিলতার দিকে তাকানো উপযুক্ত হতে পারে। যদি আপনি কোনও সাজানো তালিকায় জিনিস সংরক্ষণ করেন (যা সেখানে বাইনারি অনুসন্ধান সাহায্য করবে), এবং তারপরে কেবল অস্তিত্বের জন্য পরীক্ষা করে দেখছেন, আপনি ব্যয় করছেন (সবচেয়ে খারাপ ক্ষেত্রে, নির্দিষ্ট না করা পর্যন্ত):

সাজানো তালিকা

  • শুরুতে তালিকা তৈরি করতে ও (এন লগ এন) (যদি এটির সাজানো ডেটা না থাকে O (এন), যদি এটি সাজানো থাকে)
  • ও (লগ এন) অনুসন্ধান (এটি বাইনারি অনুসন্ধানের অংশ)
  • ও (এন) সন্নিবেশ / মুছুন (আপনার প্যাটার্নের উপর নির্ভর করে ও (1) বা ও (লগ এন) গড় ক্ষেত্রে হতে পারে)

যদিও একটি সহ set(), আপনি ব্যয় করছেন

  • ও (এন) তৈরি করতে
  • ও (1) চেহারা
  • ও (1) সন্নিবেশ / মুছুন

সাজানো তালিকার জিনিসটি আসলে আপনাকে "পরের", "পূর্ববর্তী" এবং "ব্যাপ্তি" (সীমা অন্তর্ভুক্ত করা বা মুছতে অন্তর্ভুক্ত), যা ও (1) বা ও (| রেঞ্জ |), একটি সূচক সূচক দেওয়া হয়। যদি আপনি প্রায়শই এই ধরণের ক্রিয়াকলাপটি ব্যবহার না করে থাকেন তবে সেট হিসাবে সংরক্ষণ করা এবং প্রদর্শনের জন্য বাছাই করা সামগ্রিকভাবে আরও ভাল চুক্তি হতে পারে। set()পাইথনে খুব সামান্য অতিরিক্ত ওভারহেড দেয়।


7
বাছাই করা তালিকাগুলি আপনাকে পেয়ে যায় এমন আরও একটি জিনিস রয়েছে। ও (এন) ট্র্যাভারসাল অর্ডার করেছে। ও (এন লগ এন) এর একটি সেট সহ এবং আপনাকে ডেটাতে রেফারেন্সগুলি কোনও তালিকার মধ্যে অনুলিপি করতে হবে।
সর্বসম্মত

1
যথেষ্ট সত্য! পরিসীমা অনুসন্ধানের দ্বারা আমি কী বোঝাতে চেয়েছি তার প্রসারিত করার জন্য আপনাকে ধন্যবাদ। Fww, একটি সম্পূর্ণ ট্র্যাভারসাল হ'ল কমপক্ষে, সর্বাধিকের মধ্যে একটি বিস্তৃত ক্যোয়ারী যেখানে ও (কে) যেখানে কে = এন :)
গ্রেগ লিন্ড

14

এটি উল্লেখযোগ্য হতে পারে যে দ্বিখণ্ডিত ডক্স এখন অনুসন্ধানের উদাহরণ সরবরাহ করে: http://docs.python.org/library/bisect.html#searching-sorted-lists

(-1 বা অন্য কেউ প্রত্যাবর্তনের পরিবর্তে ভ্যালুএররের উত্থাপন করা বেশি পাইথোনিক নয় - list.index () উদাহরণস্বরূপ এটি করে does তবে অবশ্যই আপনি উদাহরণগুলি আপনার প্রয়োজনের সাথে মানিয়ে নিতে পারেন))


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
দুর্দান্ত, তবে কোডটি বার্ফ করে যদি আপনি 'হাই' মানটি পাস না করেন। আমি এটি এ জাতীয়ভাবে লিখতে চাই: "ডিফ বাইনারি_সার্চ (a, x, lo = 0, হাই = কিছুই নেই): দ্বিখণ্ডিত আমদানি থেকে দ্বিখণ্ডিত i = বাইসেক্ট (ক, এক্স, লো, হাই বা লেন (ক)) রিটার্ন (আই- 1 যদি একটি [i-1] == x আর -1) "এবং এটি এর মতো পরীক্ষা করে দেখুন:" আমার জন্য পরিসীমা (1, 20): a = তালিকা (রেঞ্জ (i)) এ এএ এর জন্য: j = বাইনারি_সার্চ (a, aa) if j! = aa: i, aa, j "মুদ্রণ করুন
হুগড্রাউনটি

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

আমি সম্মত যে @ ডেভআব্রাহামসের উত্তর মডিউলটি ব্যবহার করে সঠিক পন্থা। তিনি তার উত্তরে একটি গুরুত্বপূর্ণ বিস্তারিত উল্লেখ করেননি।

ডক্স থেকে bisect.bisect_left(a, x, lo=0, hi=len(a))

দ্বিখণ্ডিত মডিউলটির আগে অনুসন্ধানের অ্যারেটি পূর্বের আগে আবশ্যক করা প্রয়োজন। bisect.bisect_leftএর ডিফল্ট 0এবং এর পরিবর্তে আপনি কেবলমাত্র এন্ডপয়েন্টগুলি উপস্থাপন করতে পারেনlen(a)

আমার ব্যবহারের জন্য আরও গুরুত্বপূর্ণ, কোনও মান X এর সন্ধান করা যাতে কোনও প্রদত্ত ফাংশনের ত্রুটি হ্রাস করা যায়। এটি করার জন্য, আমার পরিবর্তে দ্বিপদী_ বামনের অ্যালগরিদম আমার গণনা কল করার একটি উপায় প্রয়োজন। এটি সত্যিই সহজ।

সংজ্ঞায়িত করে এমন একটি বিষয় সরবরাহ করুন __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

আমার মেশিনে, "if n in l" ৩ 37 সেকেন্ড সময় নিয়েছে, যখন "if n in d" নিয়েছে 0.4 সেকেন্ড।


2
এটি বেশ কয়েকটি কারণে সর্বদা ভাল বিকল্প নয়: 1) ডিক্টস / সেটগুলি আরও মেমরি গ্রহণ করে। 2) যদি তালিকায় তার বেশি না থাকে তবে বাইনারি অনুসন্ধান দ্রুত হতে পারে। 3) তালিকাটিকে ডিকে রূপান্তর করা হ'ল একটি ও (এন) অপারেশন হয় যখন বাইনারি অনুসন্ধান হয় ও (লগ এন)।
জেসন বেকার

3
এফওয়াইআই হিসাবে পাইথন তালিকার তুলনায় পাইথনের "সেট" ওভারহেড খুব কম। এবং তারা দেখার জন্য অত্যন্ত দ্রুত। যেখানে বাইনারি অনুসন্ধানগুলি সত্যই রেঞ্জগুলি সন্ধানের জন্য অতিক্রম করে।
গ্রেগ লিন্ড

তালিকাটি রূপান্তর করা ও (এন) হতে পারে তবে তালিকায় থাকা ডেটা বাছাই করা, এটি বাইনারি অনুসন্ধানের আগে আপনাকে যা করতে হবে তা আরও খারাপ। কোথা থেকে ডেটা আসছে, আপনি সম্ভবত অভিধানে এটি inোকাতে পারেন। আমি সম্মতি দিচ্ছি যে স্মৃতিটি সমস্যা হতে পারে।
মার্ক বাকের

4

এটা হল:

  • পুনরাবৃত্তিমূলক নয় (যা এটি সর্বাধিক পুনরাবৃত্ত পদ্ধতির তুলনায় আরও মেমরি-দক্ষ করে তোলে )
  • আসলে কাজ
  • ফাস্ট যেহেতু এটি কোনো অপ্রয়োজনীয় ছাড়া সঞ্চালিত হয় যদি এর এবং শর্ত
  • একটি গাণিতিক দৃser়তা উপর ভিত্তি করে যে মেঝেতে (কম + + উচ্চ) / 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']

এটি কমপক্ষে পাইথন ২.7 -> ৩.৩ এ কাজ করা উচিত


1

ডিক ব্যবহার করা আপনার স্মৃতি ব্যবহারের দ্বিগুণ পছন্দ করবে না যদি না আপনি যে জিনিসগুলি সংরক্ষণ করেন তা সত্যই ছোট হয় না, যেহেতু মানগুলি কেবল আসল বস্তুর দিকে নির্দেশ করে:

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

উদাহরণস্বরূপ, 'foo' শুধুমাত্র একবারে সংরক্ষণ করা হয়। এটি কি আপনার জন্য কোনও পার্থক্য তৈরি করে? এবং ঠিক কতগুলি আইটেম আমরা যাইহোক সম্পর্কে কথা বলছি?


এটি সংখ্যা এবং তাদের প্রচুর সম্পর্কে :) আমি কম্পিউটারের স্মৃতি হিসাবে প্রায় বড় হিসাবে একটি অ্যারে ব্যবহার করতে চাই। আমি জানি আমার সমস্যার ভিত্তিটি ভুল হতে পারে, তবে বাইনারি অনুসন্ধান পদ্ধতির অভাব সম্পর্কে আমি কৌতূহল ছিল।
RSSlite

1
এখানে "সত্যই ক্ষুদ্র" হিসাবে যোগ্যতা অর্জনের মতো পর্যাপ্ত ছোট কী কী আপনার কাছে থাকতে পারে না। কোনও সামগ্রীর সর্বনিম্ন ব্যয় হবে 3 টি শব্দের (প্রকার, পুনঃকাউন্ট, পে-লোড), যখন একটি তালিকায় 1 শব্দ যুক্ত হবে, একটি সেট 1 শব্দ যুক্ত করবে এবং একটি ডিক 2 শব্দ যুক্ত করবে। তিনটি (তালিকা / সেট / ডিক) পাশাপাশি কিছু ফ্যাশনে প্রাকপলোকট স্পেস, যা অন্য গুণক, তবে এখনও যথেষ্ট পরিমাণে বিবেচ্য নয়।
র‌্যামফোরিঙ্কাস

1

এই কোডটি পুনরাবৃত্তির উপায়ে পূর্ণসংখ্যার তালিকার সাথে কাজ করে। সবচেয়ে সহজ কেস দৃশ্যের সন্ধান করুন, যা: দৈর্ঘ্যের তুলনায় ২ এর কম। এর অর্থ উত্তরটি ইতিমধ্যে রয়েছে এবং সঠিক উত্তরের জন্য যাচাই করার জন্য একটি পরীক্ষা করা হয়। যদি তা না হয় তবে একটি মধ্যম মানটি সঠিক হিসাবে পরীক্ষা করা হয় এবং যদি দ্বিখণ্ডিত না হয় তবে ফাংশনটি আবার কল করে, তবে মধ্যম মানটিকে উপরের বা নিম্ন সীমা হিসাবে সেট করে, এটি বাম বা ডানে সরিয়ে দিয়ে

ডিফ বাইনারি_সার্চ (ইনটলিস্ট, ইনভ্যালু, লোভ্যালু, হাইভ্যালু):
    যদি (হাইভ্যালু - লোভ্যালু) <2:
        রিটার্ন ইনটলিস্ট [লোভ্যালু] == ইনটাল্যু বা ইনটলিস্ট [হাইভ্যালিউ] == ইনটালিউ
    মিডলভ্যালু = লোভ্যালু + ((হাইভ্যালু - লোভ্যালু) / ২)
    যদি ইনটলিস্ট [মিডলভ্যালু] == ইনটওয়্যালু:
        সত্য ফিরে
    যদি ইনটলিস্ট [মিডলভ্যালু]> ইনটভ্যালু:
        বাইনারি_সার্চ রিটার্ন করুন (intList, intValue, lowValue, মাঝারি ভ্যালু - 1)
   বাইনারি_সার্চ (ইনটলিস্ট, ইনটাল্যু, মিডলভ্যালু + ১, হাইভ্যালু) রিটার্ন করুন

1

উইকিপিডিয়া http://en.wikedia.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

আমার জাঙ্গো মডেলগুলির জন্য পাইথন এবং জেনেরিকের বাইনারি অনুসন্ধানের দরকার ছিল। জাজানো মডেলগুলিতে, একটি মডেলের অন্য মডেলের বৈদেশিক কী থাকতে পারে এবং আমি পুনরুদ্ধার করা মডেলগুলির অবজেক্টগুলির জন্য কিছু অনুসন্ধান করতে চাইতাম। আমি নিম্নলিখিত ফাংশন লিখেছি আপনি এটি ব্যবহার করতে পারেন।

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 এটিকে সহজ রাখুন (কারণ আমি) বাইনারি অনুসন্ধান করার জন্য জেনেরিক দ্বিখণ্ডিত ফাংশনে নির্মিত পাইথনের বোকা ব্যবহার। বাইসেক্ট ফাংশনটির চারপাশে কিছুটা কোড সহ, আমি মনে করি যে নীচের একটি ছোট স্ট্রিং অ্যারের জন্য আমি সমস্ত কেসগুলি পরীক্ষা করেছি যেখানে নীচের উদাহরণ রয়েছে the উপরের কয়েকটি সমাধান এটির / বলতে ইঙ্গিত করে তবে আশা করি নীচের সরল কোডটি আমার মতো বিভ্রান্ত কাউকে সহায়তা করবে।

পাইথন বাইসেক্টটি বাছাই করা তালিকায় নতুন মান / সন্ধান আইটেমটি কোথায় সন্নিবেশ করানো হয় তা বোঝাতে ব্যবহৃত হয়। নীচের কোড যা দ্বিখণ্ডিত-বাম ব্যবহার করে যা তালিকায় / অ্যারেটিতে অনুসন্ধানের আইটেমটি পাওয়া গেলে হিটের সূচকটি ফিরে আসবে (নোট দ্বিখণ্ডিত এবং দ্বিখণ্ডিত-রাইট হিটের পরে উপাদানটির সূচকটি ফিরে আসবে বা সন্নিবেশ বিন্দু হিসাবে মিলবে) যদি পাওয়া না যায় , 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.