نحوه انجام جستجوی باینری برای آرایه Ruby توسط #bsearch

ما گاهی اوقات باید بررسی کنیم که آیا یک مقدار در یک آرایه گنجانده شده است یا خیر. روشهای زیادی برای دستیابی به آن وجود دارد ، به عنوان مثال Array#include?
با Array#find
، و غیره اما آنها از جستجوی خطی استفاده می کنند ، که پیچیدگی زمان است O(n)
بشر اگر آن باشد آرایه مرتب شده، ما می دانیم جستجوی دودویی می تواند به شما بدهد O(logn)
سرعت این شرم آور خواهد بود اگر نمی دانستید که آرایه روبی می تواند جستجوی باینری را از طریق جعبه انجام دهد Array#bsearch
بشر متأسفانه ، ممکن است استفاده از بسیاری از افراد برای استفاده از آن ، شهودی نباشد. بیایید ابتدا چند نمونه را ببینیم:
اگر نمی دانید چه اتفاقی در آنجا افتاده است ، می توانید به خواندن این مقاله ادامه دهید تا بدانید که
دو چیز بسیار مهم وجود دارد که باید هنگام استفاده از آن بدانید Array#bsearch
بشر اول ، فقط می توان آن را در یک انجام داد آرایه مرتب شدهبشر Array#bsearch
آرایه را برای شما مرتب نمی کند (می توانید تماس بگیرید array.sort
اول اگر مطمئن نیستید). دوم ، Array#bsearch
داشتن دو حالتبشر این بدان معناست که دو روش مختلف برای استفاده از آن دارد. حالت اول نامیده می شود حالت-minimum را پیدا کنید، و دیگری نامیده می شود حالت پیدا کردنبشر این دو حالت در واقع یک کار بسیار مشابه انجام می دهند ، اما شما باید دو بلوک کاملاً متفاوت را برای آن ارسال کنید.
حالت-minimum را پیدا کنید
هنگام استفاده از حالت Find-Minimum ،
- بلوکی که به
#bsearch
باید برگرددBoolean
ارزش ،false
یاtrue
بشر - اگر درخواست کنیم
Array.map
با همان بلوک ، باید یک سری ازfalse
مقادیر به دنبال یک سری ازtrue
مقادیر -
#bsearch
اولین عنصر بازگشت را برمی گرداندtrue
من معتقدم که هنگام دیدن نمونه های واقعی ، درک آن آسان تر است.
array = [1, 3, 5, 7, 9]
array.bsearch { |x| x >= 5 } # => 5
برمی گردد 5
، چون 5
اولین عنصری است که باعث ایجاد بلوک می شود { |x| x >= 5 }
بازگشت true
:
# compute x >= 5 for all elements
# [1, 3, 5, 7, 9 ]
[false, false, true, true, true]
اگر از دیگری به بلوک دیگری استفاده کنیم { |x| x >= 6 }
array.bsearch { |x| x >= 6 } # => 7
برمی گردد 7
بشر چرا؟ باز هم ، به این دلیل است که 7
آیا اولین عنصر بازگشت بلوک است true
# [1, 3, 5, 7, 9 ]
[false, false, false, true, true]
اگر از بلوک استفاده کنم { |x| x >= 10 }
با
array.bsearch { |x| x >= 10 } # => nil
زیرا هیچ عنصری در آرایه وجود ندارد که بتواند بلوک را بازگرداند true
، nil
بازگردانده خواهد شد
حالت پیدا کردن
هنگام استفاده از حالت Find-Any ،
- بلوکی که به
#bsearch
باید برگرددNumeric
ارزش - بازگشت شماره مثبت اگر یک عنصر آرایه باشد کوچکتر از مقادیری که در حال جستجو هستید
- بازگشت عدد منفی اگر یک عنصر آرایه باشد بیشتر از مقادیری که در حال جستجو هستید
- باید برگردد صفر، اگر عنصر با آنچه در حال جستجو است مطابقت دارد
حتی اگر قوانین فوق بسیار پیچیده تر از آن باشد حالت-minimum را پیدا کنید، به من اعتماد کن ، این نیز ساده است.
array = [1, 3, 5, 7, 9]
array.bsearch { |x| 5 <=> x } # => 5
چیست <=>
؟ این <=>
نامیده می شود مقایسه 3 طرفه، با نام مستعار اپراتور سفینه فضاییبشر اگر مقایسه کنیم a <=> b
- اگر
a < b
، سپس نتیجه است-1
- اگر
a == b
، سپس نتیجه است0
- اگر
a > b
، سپس نتیجه است1
اگر واقعاً می خواهید آن را به خاطر بسپارید ، امیدوارم که تصویر زیر بتواند به شما کمک کند:” loading=”lazy” width=”800″ height=”523″/>
به هر حال ، با بازگشت به مثال ما ، بیایید نتایج محاسبه شده را ببینیم { |x| 5 <=> x }
برای هر عنصر:
array.map { |x| 5 <=> x }
# [1, 1, 0, -1, -1]
5
بازگشت بلوک 0
، بنابراین 5
برگردانده شده است اگر سعی می کنم جستجو کنم 6
array.bsearch { |x| 6 <=> x } # => nil
این صفر را برمی گرداند زیرا نتایج محاسبه شده از { |x| 6 <=> x }
است ،
array.map { |x| 6 <=> x }
# [1, 1, 1, -1, -1]
و ندارد 0
در آن
حالت Find-Any بسیار قدرتمند است. ما می توانیم به جای یک عنصر واحد ، یک دامنه را جستجو کنیم. به عنوان مثال ،
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
array.bsearch do |x|
if x < 4
1
elsif x > 6
-1
else
0
end
end
زیرا نتایج بلوک آرایه:
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 1, 1, 0, 0, 0, -1, -1, -1, -1]
4
با 5
وت 6
بازگشت بلوک 0
، بنابراین array.bsearch
باز خواهد گشت هیچ در نتیجه یکی از آنها به همین دلیل خوانده می شود حالت پیدا کردنبشر
پایان
اگر به بالا بروید و اکنون اولین تصویر را بررسی کنید ، فکر می کنم می توانید آن را درک کنید. مهم نیست که از کدام حالت استفاده می کنید ، مهمترین چیز این است که زمان جستجو است O(logn)
بشر اگر یک آرایه مرتب شده بسیار looooong برای جستجو دارید ، و Array.find
خیلی آهسته احساس می شود (که از جستجوی خطی استفاده می کند) ، امتحان کنید Array#bsearch
، شما آن را دوست خواهید داشت! ❤