الگوریتم جستجوی دودویی

مقدمه

پیدا کردن اندیس یک عنصر خاص در یک لیست مرتب شده مفید است زیرا با استفاده از اندیس داده شده می‌توان به سایر اطلاعات مربوطه دست یافت.
فرض کنید داده ساختاری شامل مجموعه‌ای از اطلاعات نام آدرس و شماره تلفن و غیره‌است و آرایه ای که نام‌ها را دربردارد از ۱ تا N شماره‌گذاری شده‌است، یک در خواست می‌تواند این باشد: شماره فردی به نام X چند است. برای پاسخ دادن به این سؤال آرایه مورد نظر باید جستجو شده و اندیس مربوط به نام داده شده در صورت وجود برگردانده شود، در این حالت شماره تلفن ذخیره شده در آرایه تلفن‌ها در این اندیس، همان شماره فرد X است و به همین ترتیب برای آدرس و غیره نیز می‌توان عمل کرد.

بازی‌های حدس شماره

این بازی‌های ساده با چیزی شبیه این شروع می‌شوند:" من عددی را بین ۴۰ و ۶۰ در نظر گرفته‌ام و تو آن را حدس می‌زنی و من با این پاسخ‌ها تو را راهنمایی می‌کنم: کمتر، بیشتر و بله!
فرض کنید تعداد اعداد ممکن برابر N است، بنابراین  سؤال لازم است تا عدد مورد نظر پیدا شود چون هر سؤال فضای جستجو را نصف می‌کند.
حتی اگر محدودهٔ اعداد مورد نظر نا محدود باشد (یعنی توسط N محدود نشده باشد) باز هم می‌توان با حداکثر  مرحله (که K عدد انتخاب شده‌است) عدد مورد نظر را یافت. بدین ترتیب که با شروع از یک و دو برابر کردن آن در هر مرحله ابتدا مرز بالایی را پیدا نموده و سپس عدد خواسته شده را پیدا می‌کنیم. به عنوان مثال اگر عدد انتخاب شده ۱۱ باشد ما می‌توانیم ترتیب پرسش‌های زیر را برای پیدا کردن عدد دنبال کنیم: ۱ ← ۲ ← ۴ ← ۸ ← ۱۶ ← ۱۲ ← ۱۰ ← ۱۱.
هم چنین می‌توان این تکنیک را گسترش داد تا شامل اعداد منفی نیز بشود، به عنوان مثال حدس‌های زیر دنبال می‌شوند تا عدد ۱۳- پیدا شود: ۰ ← ۱- ← ۲- ← ۴- ← ۸- ← ۱۶- ← ۱۲- ← ۱۴- ← ۱۳-.

لیست‌های کلمات

انسان‌ها معمولاً ترکیبی از جستجوی دودویی و الگوریتم‌های جستجوی الحاقی را هنگام جستجوی دفترچه تلفن به کار می‌برند. بعد از حدس اولیه ما از این حقیقت استفاده می‌کنیم که ورودی‌ها مرتب اند و در نتیجه سریع تر به هدف می‌رسیم. مثلاً وقتی به دنبال «کریمی» می‌گردیم اگر «گنجی» و «قلی پور» پیدا شوند ما می‌توانیم به صفحه‌ای بین حدس‌های قبلی مراجعه کنیم و اگر مثلاً «کمالی» را نشان می‌داد می‌دانیم که صفحهٔ مورد نظر جایی بین «قلی پور» و «کمالی» خواهد بود.

تابع

برای این که وارد جزئیات تابع شویم باید قراردادهای رسمی تری را تعریف کنیم. ایده اولیه این است که داده ساختاری وجود دارد که به صورت آرایه A نمایش داده می‌شود، و المان‌های آن به صورت A(1), A(2),…,A توصیف می‌شوند و به هر ترتیبی قابل دستیابی‌اند.
داده ساختاری شامل دادهٔ دیگری به نام Key می‌شود، آرایه به گونه‌ای مرتب می‌شود که A(1).Key <= A(2).Key و ….
هدف این است که مقدار x داده شده و اندیس p پیدا شود به‌طوری‌که A(p).Key = x.
برای آغاز محدوده‌ای که باید جستجو شود کل داده‌هایی است که با متغیرهای L و R مشخص می‌شود و این مرزها در هر بار تکرار الگوریتم کاهش می‌یابند.

تکرار

Niklaus Wirth این الگوریتم را در پاسکال ارائه کرده‌است:
 i := 1;
 j := N; {array size: var A: array [1..N] of integer}
 repeat
 k := (i + j) div 2;
 if x> A[k] then
 i := k + 1
 else
 j := k - 1;
 until (A[k] = x) or (i> j);

بازگشتی

پیاده‌سازی متداول این تابع توسط الگوریتم بازگشتی زیر می‌باشد:
 BinarySearch(A[0..N-1], value, low, high) {
 if (high <low)
 return -1 // not found
 mid = low + ((high - low) / 2)  // Note: not (low + high) / 2 !!
 if (A[mid]> value)
 return BinarySearch(A, value, low, mid-1)
 else if (A[mid] <value)
 return BinarySearch(A, value, mid+1, high)
 else
 return mid // found
 }
پیاده‌سازی متداول این تابع توسط الگوریتم بازگشتی در سی شارپ به صورت زیر می‌باشد:
static bool BinarySearch(int[] A, int x, int i, int j) {
 if (i> j)
 return false;
 int m = (i + j) / 2;
 if (x> A[m])
 return BinarySearch(A, x, m + 1, j);
 else if (x <A[m])
 return BinarySearch(A, x, i, m - 1);
 else
 return true;
 }