שאלת מבחן במבני נתונים - אוניברסיטת בר-אילן 2018 - עצי B
ניצול שטח האחסון בקדקודי B-Tree הוא כ־50%. כדי להעלות את אחוז הניצול, מוצע המבנה הבא: נגדיר -Tree מסדר בדומה ל־B-Tree מסדר רק שעבור כל קדקוד שאינו השורש נדרוש שמספר בניו יקיים ולא רק . כדי לטפל בפיצולים, לא נאפשר פיצול של קדקוד בודד ל־2 קדקודים, אלא תמיד נפצל קדקוד גולש (עם overflow) יחד עם אחד מאחיו המלאים (אך לא גולשים), דהיינו, 2 קדקודים יהפכו ל־3 קדקודים, כ"א מלא עד כדי 2/3. (לא נטפל במחיקות ואיחודים בשאלה זו.)
א) בדוגמה הבאה (בה מצוייר רק חלק מ־-Tree), הנח/י :
(בתרשים נתון קודקוד אב עם המפתחות 7, 110, 300, 350. לקודקוד זה בן שמאלי עם המפתחות 10, 15, 20, 50, 70, 82, ובן ימני עם המפתחות 200, 220, 230, 240, 250, 260).
נניח שנוסיף את הערך 60 מה שיגרום גלישה בקדקוד . צייר/י את חלק העץ הרלוונטי אחרי פיצול 2 הקדקודים ו־ ל־3 קדקודים, כולל התיקונים הדרושים בקדקוד .
ב) מה עושים אם השכן של קדקוד גולש אינו מלא?
ג) לשורש אין אחים. אם נרצה שבניו של השורש אחרי פיצול גם יקיימו את התנאי ש־, איך צריך לשנות את התנאי לשורש (היות ויש רק שורש אחד, אין בעיה לחרוג מהמגבלות על הקדקודים רק עבור השורש)?
א) בדוגמה הבאה (בה מצוייר רק חלק מ־-Tree), הנח/י :
(בתרשים נתון קודקוד אב עם המפתחות 7, 110, 300, 350. לקודקוד זה בן שמאלי עם המפתחות 10, 15, 20, 50, 70, 82, ובן ימני עם המפתחות 200, 220, 230, 240, 250, 260).
נניח שנוסיף את הערך 60 מה שיגרום גלישה בקדקוד . צייר/י את חלק העץ הרלוונטי אחרי פיצול 2 הקדקודים ו־ ל־3 קדקודים, כולל התיקונים הדרושים בקדקוד .
ב) מה עושים אם השכן של קדקוד גולש אינו מלא?
ג) לשורש אין אחים. אם נרצה שבניו של השורש אחרי פיצול גם יקיימו את התנאי ש־, איך צריך לשנות את התנאי לשורש (היות ויש רק שורש אחד, אין בעיה לחרוג מהמגבלות על הקדקודים רק עבור השורש)?
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
אוניברסיטת בר-אילןמועד א2018סמסטר ב
★★★★★
עצי B
עבור סעיף א', אסוף את כל המפתחות מהקודקוד הגולש, אחיו המלא, והמפתח המפריד מהאב, וחלק אותם מחדש לשלושה קודקודים חדשים ושני מפתחות שיעלו לאב. עבור סעיף ג', חשוב כמה מפתחות (ובנים) צריך שיהיו בשורש כדי שבפיצול של 1 ל-2, שני הבנים החדשים יעמדו בדרישת המינימום.
א) עבור , מספר הבנים המינימלי לקודקוד שאינו השורש הוא . מספר המפתחות המינימלי הוא והמקסימלי הוא . הקודקודים ו- מלאים (6 מפתחות כ"א).
הוספת המפתח 60 לקודקוד גורמת לו לגלוש, מכיוון שכעת יש בו 7 מפתחות: {10, 15, 20, 50, 60, 70, 82}.
לפי האלגוריתם, יש לפצל את הקודקוד הגולש יחד עם אחיו המלא . התהליך כולל מיזוג המפתחות של (לאחר ההוספה), המפתחות של , והמפתח המפריד ביניהם מהאב (שהוא 110).
1. איסוף המפתחות:
- מפתחות (עם 60): {10, 15, 20, 50, 60, 70, 82} (7 מפתחות)
- מפתח מפריד מ-: {110} (מפתח 1)
- מפתחות : {200, 220, 230, 240, 250, 260} (6 מפתחות)
סה"כ יש מפתחות.
2. חלוקה ל-3 קודקודים: יש לחלק את 14 המפתחות ל-3 קודקודים חדשים ו-2 מפתחות שיעלו לאב. כל קודקוד חדש יכיל 4 מפתחות (המספר המינימלי), וסה"כ מפתחות יחולקו בין הבנים.
רשימת המפתחות הממוינת: {10, 15, 20, 50, 60, 70, 82, 110, 200, 220, 230, 240, 250, 260}.
המפתחות שיעלו לאב הם אלו שמפרידים בין 3 קבוצות של 4 מפתחות. אלו הם המפתח ה-5 (60) והמפתח ה-10 (220) ברשימה.
3. הקודקודים החדשים:
- קודקוד חדש : {10, 15, 20, 50}
- קודקוד חדש : {70, 82, 110, 200}
- קודקוד חדש : {230, 240, 250, 260}
כל אחד מהקודקודים החדשים מכיל 4 מפתחות, ולכן יהיו לו 5 בנים, מה שמקיים את תנאי המינימום ().
4. **עדכון האב **:
- המפתחות המקוריים של : {7, 110, 300, 350}
- מסירים את המפתח 110 שהפריד בין ל- וירד למטה.
- מוסיפים את שני המפתחות החדשים שעלו, 60 ו-220.
- המפתחות החדשים ב-: {7, 60, 220, 300, 350}.
המצב הסופי של חלק העץ הרלוונטי הוא:
- **קודקוד אב ** עם המפתחות: {7, 60, 220, 300, 350}
- המצביע בין 7 ל-60 מוביל לקודקוד **** עם המפתחות: {10, 15, 20, 50}
- המצביע בין 60 ל-220 מוביל לקודקוד **** עם המפתחות: {70, 82, 110, 200}
- המצביע בין 220 ל-300 מוביל לקודקוד **** עם המפתחות: {230, 240, 250, 260}
ב) אם השכן של קודקוד גולש אינו מלא, לא ניתן לבצע את פיצול ה-2-ל-3, מכיוון שאין מספיק מפתחות כדי להבטיח שכל שלושת הקודקודים החדשים יעמדו בתנאי המינימום. במקרה כזה, נשתמש בטכניקה הסטנדרטית של גלגול (rotation) מפתחות, בדומה ל-B-Tree רגיל. מעבירים מפתח מהקודקוד הגולש, דרך האב, אל השכן שאינו מלא. פעולה זו מאזנת מחדש את מספר המפתחות בין שני האחים ופותרת את הגלישה ללא צורך בפיצול.
ג) לשורש אין אחים, ולכן אם הוא גולש, חובה לפצל אותו. פיצול רגיל של 1-ל-2 עלול ליצור שני בנים שאינם מקיימים את תנאי המילוי של 2/3. לדוגמה, עבור פיצול של שורש עם 7 מפתחות ייצור שני בנים עם 3 מפתחות כל אחד (4 בנים), בעוד הנדרש הוא מינימום 4 מפתחות (5 בנים).
כדי להבטיח שבניו של השורש לאחר פיצול יקיימו את התנאי, עלינו לשנות את הכלל עבור השורש ולאפשר לו להכיל יותר מפתחות לפני שהוא מתפצל. נדרוש שהשורש יתפצל רק כאשר מספר בניו מגיע לגודל כזה שחלוקתו ל-2 תיתן קודקודים תקינים. נסמן את מספר הבנים המינימלי לקודקוד רגיל . לאחר פיצול 1-ל-2 של השורש, לכל בן חדש יהיו לפחות בנים. כדי לקיים את הדרישה, עלינו לדרוש . התנאי הפשוט ביותר המבטיח זאת הוא .
לכן, יש לשנות את התנאי כך שהשורש יורשה לגדול עד שיש לו מפתחות (ו- בנים). רק כאשר מנסים להוסיף לשורש כזה מפתח נוסף, הוא יתפצל ל-2, ושני בניו החדשים יכילו כל אחד לפחות בנים, ויקיימו את תנאי המבנה.
הוספת המפתח 60 לקודקוד גורמת לו לגלוש, מכיוון שכעת יש בו 7 מפתחות: {10, 15, 20, 50, 60, 70, 82}.
לפי האלגוריתם, יש לפצל את הקודקוד הגולש יחד עם אחיו המלא . התהליך כולל מיזוג המפתחות של (לאחר ההוספה), המפתחות של , והמפתח המפריד ביניהם מהאב (שהוא 110).
1. איסוף המפתחות:
- מפתחות (עם 60): {10, 15, 20, 50, 60, 70, 82} (7 מפתחות)
- מפתח מפריד מ-: {110} (מפתח 1)
- מפתחות : {200, 220, 230, 240, 250, 260} (6 מפתחות)
סה"כ יש מפתחות.
2. חלוקה ל-3 קודקודים: יש לחלק את 14 המפתחות ל-3 קודקודים חדשים ו-2 מפתחות שיעלו לאב. כל קודקוד חדש יכיל 4 מפתחות (המספר המינימלי), וסה"כ מפתחות יחולקו בין הבנים.
רשימת המפתחות הממוינת: {10, 15, 20, 50, 60, 70, 82, 110, 200, 220, 230, 240, 250, 260}.
המפתחות שיעלו לאב הם אלו שמפרידים בין 3 קבוצות של 4 מפתחות. אלו הם המפתח ה-5 (60) והמפתח ה-10 (220) ברשימה.
3. הקודקודים החדשים:
- קודקוד חדש : {10, 15, 20, 50}
- קודקוד חדש : {70, 82, 110, 200}
- קודקוד חדש : {230, 240, 250, 260}
כל אחד מהקודקודים החדשים מכיל 4 מפתחות, ולכן יהיו לו 5 בנים, מה שמקיים את תנאי המינימום ().
4. **עדכון האב **:
- המפתחות המקוריים של : {7, 110, 300, 350}
- מסירים את המפתח 110 שהפריד בין ל- וירד למטה.
- מוסיפים את שני המפתחות החדשים שעלו, 60 ו-220.
- המפתחות החדשים ב-: {7, 60, 220, 300, 350}.
המצב הסופי של חלק העץ הרלוונטי הוא:
- **קודקוד אב ** עם המפתחות: {7, 60, 220, 300, 350}
- המצביע בין 7 ל-60 מוביל לקודקוד **** עם המפתחות: {10, 15, 20, 50}
- המצביע בין 60 ל-220 מוביל לקודקוד **** עם המפתחות: {70, 82, 110, 200}
- המצביע בין 220 ל-300 מוביל לקודקוד **** עם המפתחות: {230, 240, 250, 260}
ב) אם השכן של קודקוד גולש אינו מלא, לא ניתן לבצע את פיצול ה-2-ל-3, מכיוון שאין מספיק מפתחות כדי להבטיח שכל שלושת הקודקודים החדשים יעמדו בתנאי המינימום. במקרה כזה, נשתמש בטכניקה הסטנדרטית של גלגול (rotation) מפתחות, בדומה ל-B-Tree רגיל. מעבירים מפתח מהקודקוד הגולש, דרך האב, אל השכן שאינו מלא. פעולה זו מאזנת מחדש את מספר המפתחות בין שני האחים ופותרת את הגלישה ללא צורך בפיצול.
ג) לשורש אין אחים, ולכן אם הוא גולש, חובה לפצל אותו. פיצול רגיל של 1-ל-2 עלול ליצור שני בנים שאינם מקיימים את תנאי המילוי של 2/3. לדוגמה, עבור פיצול של שורש עם 7 מפתחות ייצור שני בנים עם 3 מפתחות כל אחד (4 בנים), בעוד הנדרש הוא מינימום 4 מפתחות (5 בנים).
כדי להבטיח שבניו של השורש לאחר פיצול יקיימו את התנאי, עלינו לשנות את הכלל עבור השורש ולאפשר לו להכיל יותר מפתחות לפני שהוא מתפצל. נדרוש שהשורש יתפצל רק כאשר מספר בניו מגיע לגודל כזה שחלוקתו ל-2 תיתן קודקודים תקינים. נסמן את מספר הבנים המינימלי לקודקוד רגיל . לאחר פיצול 1-ל-2 של השורש, לכל בן חדש יהיו לפחות בנים. כדי לקיים את הדרישה, עלינו לדרוש . התנאי הפשוט ביותר המבטיח זאת הוא .
לכן, יש לשנות את התנאי כך שהשורש יורשה לגדול עד שיש לו מפתחות (ו- בנים). רק כאשר מנסים להוסיף לשורש כזה מפתח נוסף, הוא יתפצל ל-2, ושני בניו החדשים יכילו כל אחד לפחות בנים, ויקיימו את תנאי המבנה.