الگوریتم جستجوی دودویی
الگوریتم جستجوی دودویی (به انگلیسی: Binary Search) یا جستجوی دودویی خوارزمی، تکنیکی است برای یافتن یک مقدار عددی از میان مجموعهای از اعداد مرتب. این متد محدودهٔ جستجو را در هر مرحله به نصف کاهش میدهد، بنابراین هدف مورد نظر یا به زودی پیدا میشود یا مشخص میشود که مقدار مورد جستجو در فهرست وجود ندارد.
رده | الگوریتم جستجو |
---|---|
ساختمان داده | آرایه (ساختار داده) |
کارایی بدترین حالت | O(log n) |
کارایی بهترین حالت | O(1) |
کارایی متوسط | O(log n) |
پیچیدگی فضایی | O(1) |
جستجوی دودویی فقط در آرایههای مرتب استفاده میشود. در این روش عنصر مورد نظر با خانه وسط آرایه مقایسه میشود اگر با این خانه برابر بود جستجو تمام میشود اگر عنصر مورد جستجو از خانه وسط بزرگتر بود جستجو در بخش بالایی آرایه و در غیر این صورت جستجو در بخش پایینی آرایه انجام میشود (فرض کردهایم آرایه به صورت صعودی مرتب شدهاست) این رویه تا یافتن عنصر مورد نظر یا بررسی کل خانههای آرایه ادامه مییابد.
جستجوی دودویی نمونهای از الگوریتمهای تقسیم و غلبه (به انگلیسی: Divide and conquer) میباشد.
مقدمه
پیدا کردن اندیس یک عنصر خاص در یک لیست مرتب شده مفید است زیرا با استفاده از اندیس داده شده میتوان به سایر اطلاعات مربوطه دست یافت.
فرض کنید داده ساختاری شامل مجموعهای از اطلاعات نام آدرس و شماره تلفن و غیرهاست و آرایه ای که نامها را دربردارد از ۱ تا N شمارهگذاری شدهاست، یک در خواست میتواند این باشد: شماره فردی به نام X چند است. برای پاسخ دادن به این سؤال آرایه مورد نظر باید جستجو شده و اندیس مربوط به نام داده شده در صورت وجود برگردانده شود، در این حالت شماره تلفن ذخیره شده در آرایه تلفنها در این اندیس، همان شماره فرد X است و به همین ترتیب برای آدرس و غیره نیز میتوان عمل کرد.
خواص درخت دودویی
n تعداد گرهها در یک درخت دودویی کامل است و با استفاده از این فرمول میتوان آن را یافت
N تعداد گرهها در یک درخت دودویی کامل نیز میتواند با استفاده فرمول
تعدادی از لینکهای تهی (فرزندان غایب از گرهها) در یک درخت دودویی کامل از n گره
اثبات:
N = تعداد کل گره B = تعداد شاخهها
- n0, n1, n2 برای نشان دادن تعداد گره بدون فرزند، تنها یک فرزند و دو فرزند بود
- B = n - 1 (از آنجا که تمام گرهها به جز گره ریشه از شاخه واحد)
- B = n1 + 2*n2
- n = n1+ 2*n2 + 1
- n = n0 + n1 + n2
- n1+ 2*n2 + 1 = n0 + n1 + n2 ==> n0 = n2 + 1
مثال
بازیهای حدس شماره
این بازیهای ساده با چیزی شبیه این شروع میشوند:" من عددی را بین ۴۰ و ۶۰ در نظر گرفتهام و تو آن را حدس میزنی و من با این پاسخها تو را راهنمایی میکنم: کمتر، بیشتر و بله!
فرض کنید تعداد اعداد ممکن برابر N است، بنابراین
حتی اگر محدودهٔ اعداد مورد نظر نا محدود باشد (یعنی توسط N محدود نشده باشد) باز هم میتوان با حداکثر
هم چنین میتوان این تکنیک را گسترش داد تا شامل اعداد منفی نیز بشود، به عنوان مثال حدسهای زیر دنبال میشوند تا عدد ۱۳- پیدا شود: ۰ ← ۱- ← ۲- ← ۴- ← ۸- ← ۱۶- ← ۱۲- ← ۱۴- ← ۱۳-.
لیستهای کلمات
انسانها معمولاً ترکیبی از جستجوی دودویی و الگوریتمهای جستجوی الحاقی را هنگام جستجوی دفترچه تلفن به کار میبرند. بعد از حدس اولیه ما از این حقیقت استفاده میکنیم که ورودیها مرتب اند و در نتیجه سریع تر به هدف میرسیم. مثلاً وقتی به دنبال «کریمی» میگردیم اگر «گنجی» و «قلی پور» پیدا شوند ما میتوانیم به صفحهای بین حدسهای قبلی مراجعه کنیم و اگر مثلاً «کمالی» را نشان میداد میدانیم که صفحهٔ مورد نظر جایی بین «قلی پور» و «کمالی» خواهد بود.
تابع
برای این که وارد جزئیات تابع شویم باید قراردادهای رسمی تری را تعریف کنیم. ایده اولیه این است که داده ساختاری وجود دارد که به صورت آرایه A نمایش داده میشود، و المانهای آن به صورت A(1), A(2),…,A توصیف میشوند و به هر ترتیبی قابل دستیابیاند.
داده ساختاری شامل دادهٔ دیگری به نام Key میشود، آرایه به گونهای مرتب میشود که A(1).Key <= A(2).Key و ….
هدف این است که مقدار x داده شده و اندیس p پیدا شود بهطوریکه A(p).Key = x.
برای آغاز محدودهای که باید جستجو شود کل دادههایی است که با متغیرهای L و R مشخص میشود و این مرزها در هر بار تکرار الگوریتم کاهش مییابند.
پیادهسازی
تکرار
یکی از روش ها برای پیدا کردن عنصر مورد نظر x در یک آرایه بنام A روش تکرار است،که مراحل زیر را شامل می شود:
1.دو متغیر i و j به ترتیب مقادیر اولیه 0 و n-1 را می گیرند.(n طول آرایه مورد نظر است.)
2.تا زمانیکه
2.1.متغیر k مقدار
2.2.اگر
2.3.اگر
3.حال
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; }
دیگر کاربردها
یافتن عنصر سمت چپ
برای یافتن عنصر سمت چپ عنصر مورد نظرمان یعنی T در آرایه A به ترتیب زیر عمل میکنیم:
1.به ترتیب به L و R مقادیر اولیه 0 و n را می دهیم.
2.تازمانیکه L<R باشد مراحل زیر را تکرار میکنیم:
2.1.مقدار
2.2.اگر
2.3.اگر
3.مقدار L خروجی داده می شود.
شبه کد زیر این مراحل را نشان می دهد:
binary_search_leftmost(A, n, T):
L = 0
R = n
while L < R:
m = floor((L + R) / 2)
if A[m] < T:
L = m + 1
else:
R = m
return L
یافتن عنصر سمت راست
برای یافتن عنصر سمت چپ عنصر مورد نظرمان یعنی T در آرایه A به ترتیب زیر عمل میکنیم:
1.به ترتیب به L و R مقادیر اولیه 0 و n را می دهیم.
2.تازمانیکه L<R باشد مراحل زیر را تکرار میکنیم:
2.1.مقدار
2.2.اگر
2.3.اگر
3.مقدار R-1 خروجی داده می شود.
شبه کد زیر این مراحل را نشان می دهد:
binary_search_rightmost(A, n, T):
L = 0
R = n
while L < R:
m = floor((L + R) / 2)
if A[m] > T:
R = m
else:
L = m + 1
return R - 1
منابع
- دانلد کنوت. The Art of Computer Programming, Volume 3: Sorting and Searching, Third Edition. Addison-Wesley, 1997. ISBN 0-201-89685-0. Section 6.2.1: Searching an Ordered Table, pp. 409–426.
- Kruse, Robert L. : "Data Structures and Program Design in C++", Prentice-Hall, 1999, ISBN 0-13-768995-0, page 280.
- http://en.wikipedia.org/wiki/Binary_search_algorithm
پیوند به بیرون
- NIST Dictionary of Algorithms and Data Structures: binary search
- Binary Search using C++ بایگانیشده در ۵ مارس ۲۰۰۹ توسط Wayback Machine
- Binary Search using PHP
- Binary Search using CSharp
- [ ]