חיפוש אקספוננציאלי

האלגוריתם

חיפוש אקספוננציאלי מאפשר לחפש ברשימה ממוינת, בלתי חסומה, ערך קלט (האיבר לחיפוש). האלגוריתם מורכב משני שלבים. השלב הראשון קובע טווח שבו האיבר שמחפשים צריך להיות במידה והוא נמצא ברשימה. בשלב השני, מבצעים חיפוש בינארי על טווח זה. בשלב הראשון, בהנחה שהרשימה ממוינת בסדר עולה, האלגוריתם מחפש את החזקה הראשונה, j, כך שהערך  גדול יותר מהאיבר שמחפשים. ערך זה, הופך להיות הגבול העליון עבור החיפוש הבינארי, כאשר החזקה הקודמת של 2,  הינה הגבול התחתון עבור החיפוש הבינארי.
// Returns the position of key in the array arr of length size.template <typename T>int exponential_search(T arr[], int size, T key){
 if (size == 0) {
 return NOT_FOUND;
 }

 int bound = 1;
 while (bound < size && arr[bound] < key) {
 bound *= 2;
 }

 return binary_search(arr, key, bound/2, min(bound, size));}
בכל שלב, האלגוריתם משווה את האיבר שמחפשים עם האיבר באינדקס הנוכחי. אם האיבר באינדקס הנוכחי קטן יותר מהערך שמחפשים, האלגוריתם מתבצע שוב, תוך דילוג לאינדקס הבא על ידי הכפלתו, מה שגורם לחישוב החזקה הבאה של 2. אם האיבר באינדקס הנוכחי גדול מהאיבר שמחפשים, האלגוריתם יודע עכשיו כי איבר החיפוש, אם נמצא ברשימה, ממוקם בטווח שנוצר על ידי אינדקס החיפוש הקודם, , לאינדקס החיפוש הנוכחי, . לאחר מכן מבצעים חיפוש בינארי כאשר התוצאה היא או כישלון, אם האיבר לחיפוש לא נמצא ברשימה, או המיקום של האיבר ברשימה.

ניתוח

השלב הראשון של האלגוריתם לוקח  זמן, כאשר i הוא האידקס בו האיבר לחיפוש צריך להמצא ברשימה. זה כי, בקביעת הגבול העליון עבור חיפוש בינארי, לולאת הwhile מבוצעת בדיוק  פעמים. היות שהרשימה ממוינת, לאחר הכפלת אינדקס החיפוש  פעמים, האלגוריתם יגיע לאינדקס חיפוש גדול או שווה לi, כיוון ש . כאמור, השלב הראשון של האלגוריתם לוקח  זמן.
החלק השני של האלגוריתם גם לוקח  זמן. כיוון שהשלב השני הוא פשוט חיפוש בינארי, זה לוקח , כאשר n הוא גודל הטווח שבו מחפשים. גודל טווח זה יהיה , כאשר, כפי שמופיע לעיל, . זה אומר כי גודל הטווח לחיפוש הוא . זה נותן לנו זמן ריצה של .
סה"כ זמן הריצה הכולל של האלגוריתם, המחושב על ידי סכום זמני הריצה של שני השלבים, הוא של .

גרסאות נוספות

בנטלי ויאו הציעו מספר גרסאות לחיפוש אקספוננציאלי. גרסאות אלו מורכבות מביצוע חיפוש בינארי, לעומת חיפוש אונרי, לקביעת הגבול העליון של החיפוש הבינארי בשלב השני של האלגוריתם. דבר זה מחלק את השלב הראשון של האלגוריתם לשני חלקים, המסתכמים לכדי 3 שלבים של האלגוריתם בכללותו. בדומה למקודם, השלב הראשון החדש קובע ערך , כך ש  גדול יותר מהערך לחיפוש, ו- קטן יותר מהערך שמחפשים. מקודם,  נקבע באמצעות חיפוש אונרי על ידי חישוב החזקה הבאה של 2 (כלומר, הוספת 1 ל-j). בגרסה זו, מוצע תחת זאת להכפיל את  (לדוגמה, לקפוץ מ ל-, במקום ). ה- הראשון כך ש- גדול יותר מהערך שמחפשים, מהווה חסם עליון גס יותר ממקודם. כאשר מוצאים את , האלגוריתם עובר לשלב השני ומבצע חיפוש בינארי על הטווח בין  ל-, שנותן חסם עליון עליון מדויק יותר על החזקה j. מנקודה זו, השלב השלישי של האלגוריתם מבצע חיפוש בינארי על הטווח שבין  ל-, כמקודם. זמן הריצה של גרסה זו הוא .
בנטלי ויאו הכלילו את הווריאציה הזו לגרסה בה מספר כלשהו, k, של חיפושים בינאריים מתבצע במהלך השלב הראשון של האלגוריתם, מה שנותן גרסה של k-חיפושים בינאריים מקוננים. זמן הריצה האסימפטוטי אינו שונה בשתי הגרסאות, פועל ב- זמן, כמו באלגוריתם החיפוש האקספוננציאלי המקורי.
כמו כן, ניתן לתת מבנה נתונים עם גרסה חזקה של תכונת האצבע הדינמית (עץ Splay) כאשר משתמשים בתוצאה לעיל של k- חיפושים בינאריים מקוננים על מערך ממוין. תוך שימוש במבנה נתונים זה, מספר ההשוואות שמבוצעות במהלך חיפוש הוא , כאשר d הוא ההפרש בדרגה בין האיבר האחרון שהתבצעה גישה אליו והאיבר הנוכחי שנגשים אליו.