ערימה בינומית

במדעי המחשב, ערימה בינומית היא סוג של מבנה הנתונים ערימה. היא ממומשת בעזרת אוסף עצים בינומים. יתרונה הוא שהיא מאפשרת מיזוג שתי ערימות במהירות. ערימה בינומית מהווה מימוש יעיל של מבנה הנתונים המופשט תור עדיפויות. ערימה בינומית ממומשת כאוסף של עצים בינומיים. כל עץ בינומי מקיים את "כלל הערימה": ערך כל צומת קטן יותר מערכי כל בניו (ערימה כזאת נקראת "ערימת מינימום". ניתן גם לבנות "ערימת מקסימום", בה כל צומת גדול מבניו). ערימה בינומית מקיימת את השמורה הבאה: לכל i, יש בערימה לכל היותר עץ אחד מדרגה i. דרגה של עץ בינומי מוגדרת על ידי מס' הצמתים בעץ, כך שעץ מדרגה 0 הוא שורש בלבד, ובעץ מדרגה i יש 2 i {\displaystyle 2^{i}} קודקודים. כתוצאה מכך יש מבנה אפשרי יחיד לערימה, הנובע מהייצוג הבינארי של גודלה. (לדוגמה, בערימה מגודל 25 (11001 בבסיס בינארי) יהיה עץ אחד מדרגה 0, עץ אחד מדרגה 3 ועץ אחד מדרגה 4). את שורשי העצים ניתן להחזיק ברשימה מקושרת כפולה (כלומר עם מצביעים אחורה). בערימה בינומית יש לכל היותר עץ אחד מכל דרגה. לפיכך, בערימה בינומית בה דרגת העץ המקסימלי היא i יש לכל היותר 2^(i+1) איברים. לפיכך, בערימה בינומית בה יש m איברים- יש לכל היותר log ⁡ m {\displaystyle \log m} עצים. הפעולה המעניינת והחשובה ביותר בערימה בינומית היא מיזוג: בהינתן שתי ערימות, ממזגים אותן בדומה לחיבור בינארי: עוברים על הדרגות מהקטנה לגדולה, ובכל דרגה, אם יש רק עץ אחד מדרגה כזו מכניסים לערימה המאוחדת. אם יש שניים, מאחדים אותם ומתייחסים אליהם כאל עץ מדרגה גדולה יותר (בדומה לנשא בחיבור רגיל). כיוון שישנם כ-log m עצים בכל ערימה, הסיבוכיות היא O ( log ⁡ m ) {\displaystyle O(\log m)} . כעת נבחן כיצד לממש את שאר פעולות הערימה באמצעות פעולות המיזוג: כדי להכניס אלמנט חדש, נבנה ערימה חדשה מדרגה 1 ונמזג אותה עם הערימה הקיימת. סיבוכיות הפעולה היא O ( log ⁡ m ) {\displaystyle O(\log m)} (כש-m הוא גודל הערימה), אך ניתוח לשיעורין מביא לתוצאה של O ( 1 ) {\displaystyle O(1)} . (ומכאן שבניית ערימה מ-m איברים לוקחת O ( m ) {\displaystyle O(m)} ) הואיל וכל אחד משורשי העצים בערימה מקיים את תכונת הערימה, הרי שאיבר המינימום בערימה הוא אחד משורשי העצים. הואיל ובערימה בת m איברים יש log m שורשי עצים, ניתן למצוא את שורש המינימום ב- O(log m)‎. מוצאים את איבר המינימום ומוחקים אותו. (ניתן, כשיפור, להחזיק מצביע לאיבר המינימלי, כך שמציאתו לוקחת O ( 1 ) {\displaystyle O(1)} .) כיוון שילדיו של עץ מדרגה i הם שורשים של עצים מדרגות i-1‏,...,0,1, ניתן להסתכל על שורשיו כערימה בינומית מסדר i-1. כעת מבצעים מיזוג בין הערימה החדשה הזו לשאר הערימה. סיבוכיות: O ( log ⁡ m ) {\displaystyle O(\log m)} . כיוון שערימה אינה תומכת בחיפוש, מחיקה צריכה לבוא עם מצביע לאיבר הנמחק. כדי למחוק מחליפים את ערך הצומת עם אביו, ואז שוב עד לשורש (פעולה זאת לוקחת כעומק המקסימלי של עץ שהוא כ-log m), ואז מוחקים אותו וממזגים את בניו עם שאר הערימה. סיבוכיות: O ( log ⁡ m ) {\displaystyle O(\log m)} . בהינתן מצביע לצומת מסוים, מקטינים את המפתח, ואם הוא קטן מאביו, מחליפים ביניהם, ושוב אם הוא קטן מאביו מחליפים ביניהם עד שהוא גדול מאביו (או מגיע לשורש), סיבוכיות: O ( log ⁡ m ) {\displaystyle O(\log m)} . שיפור בסיבוכיות של פעולה זו אפשרי על ידי שימוש בערימת פיבונאצ'י, המבוססת על ערמה בינומית, בה עלות הקטנת מפתח בניתוח לשיעורין היא O ( 1 ) {\displaystyle O(1)} . ערימה בינומית עצלה ממומשת בדומה לערמה, אך היא לא משמרת את המבנה כל הזמן: בפעולות הכנסה ומיזוג פשוט משרשרים את האיבר החדש או הערימה החדשה לקיימת (ב- O ( 1 ) {\displaystyle O(1)} ) ואילו בפעולת המחיקה מתקנים תוך כדי את הערימה לערימה בינומית תקינה, פעולה זאת לוקחת O ( n ) {\displaystyle O(n)} , אך בניתוח לשיעורין עלותה הוא O ( log ⁡ n ) {\displaystyle O(\log n)} . בערימת פיבונאצ'י העצים כלל אינם עצים בינומיים: בכל פעולת הקטנת הערך חותכים את הצומת ויוצרים ממנו עץ חדש, וכאשר מוחקים כך שני בנים של צומת חותכים גם אותו. כתוצאה מכך העלות של פעולת הקטנת המפתח עולה ל- O ( n ) {\displaystyle O(n)} , אך עלותה לשיעורין יורדת ל- O ( 1 ) {\displaystyle O(1)} . בשל כך היא טובה לאלגוריתמים שדורשים הקטנות רבות של המפתחות (כדוגמת אלגוריתם דייקסטרה שבערימת פיבונאצ'י סיבוכיותו היא   O ( | E | + | V | log ⁡ | V | ) {\displaystyle \ O(|E|+|V|\log |V|)} לעומת   O ( | E | log ⁡ | V | ) {\displaystyle \ O(|E|\log |V|)} בערימה בינארית). מדיה וקבצים בנושא ערימה בינומית בוויקישיתוף O(1)‎ - בניתוח לשיעורין עבור n הכנסות רצופות בדומה למונה בינארי