יסודות מבני נתונים תרגול 6: עץ (Tree), עץ בינארי (Binary Tree), עץ חיפוש בינארי (BST - Binary Search Tree)
עץTree – עץ – מבנה נתונים המורכב מאוסף של צמתים (קדקודים) וקשתות עם יחס היררכי (הורה-ילד). כל צומת מורכבת מנתונים שמאוחסנים בה, ומאוסף של מצביעים לילדים של הצומת. שורש הורה אבות קדמונים של d ילד צאצאים של b
עץTree – עץ – מבנה נתונים המורכב מאוסף של צמתים (קדקודים) וקשתות עם יחס היררכי (הורה-ילד). כל צומת מורכבת מנתונים שמאוחסנים בה, ומאוסף של מצביעים לילדים של הצומת. צמתים פנימיים עלים
עץTree – עץ – מבנה נתונים המורכב מאוסף של צמתים (קדקודים) וקשתות עם יחס היררכי (הורה-ילד). כל צומת מורכבת מנתונים שמאוחסנים בה, ומאוסף של מצביעים לילדים של הצומת. גובה של עץ הוא גובה של השורש גובה של b- המסלול הארוך ביותר בתת העץ של b עומק של f – אורך המסלול מ f לשורש
עץ בינאריBinary Tree – עץ בינארי – עץ שבו לכל צומת יש לכל היותר שני ילדים (ימני ושמאלי). דוגמא: סריקות של עץ בינארי pre-order – שורש, תת עץ שמאלי, תת עץ ימני a,b,d,e,g,h,c,f in-order – תת עץ שמאלי, שורש, תת עץ ימני d,b,g,e,h,a,c,f post-order – תת עץ שמאלי, תת עץ ימני, שורש d,g,h,e,b,a,f,c
Question 1 Solution: From the pre-order we can see that “a” is the root. Given this, from post-order we can divide nodes into left sub-tree [c,d,b] and right sub-tree [h,g,j,e,f].
Question 1
Question 2 האם ניתן לשחזר עץ בהנתן סריקות pre-order ו post-order ? תשובה: לא תמיד. דוגמא: pre-order: a,b post-order: b,a שני העצים אפשריים או a a b b
עץ חיפוש בינאריBinary Search Tree – החל מהשורש, שמאלה עד הסוף החל מהשורש, ימינה עד הסוף
עץ חיפוש בינאריBinary Search Tree – החל מהשורש, שמאלה עד הסוף החל מהשורש, ימינה עד הסוף החל מהצומת x, ימינה פעם אחת, ואז שמאלה עד הסוף דוגמא: Successor (T, 20) = 24 או למעלה עד שיש פעם אחת "למעלה ימינה" דוגמא: Successor (T, 28) = 30
עץ חיפוש בינאריBinary Search Tree – החל מהשורש, שמאלה עד הסוף החל מהשורש, ימינה עד הסוף החל מהצומת x, ימינה פעם אחת, ואז שמאלה עד הסוף דוגמא: Successor (T, 20) = 24 או למעלה עד שיש פעם אחת "למעלה ימינה" דוגמא: Successor (T, 28) = 30 החל מהצומת x, שמאלה פעם אחת, ואז ימינה עד הסוף דוגמא: Predecessor (T, 30) = 28 או למעלה עד שיש פעם אחת "למעלה שמאלה" דוגמא: Predecessor (T, 24) = 20
עץ חיפוש בינאריBinary Search Tree – with s
Question 3 בהנתן עץ חיפוש בינארי T ושתי מפתחות K1 ו K2, הציעו אלגוריתם המדפיס את כל הצמתים x של T אשר מקיימים K1 ≤ x.key ≤ K2. פתרון: נשתמש בסריקת inorder על העץ T עם שינוי קטן. נבדוק את הערך של השורש. אם השורש גדול מ 1K אז נלך רקורסיבית לתת עץ השמאלי. אם השורש בתחום אז נדפיס את המפתח של השורש. אם השורש קטן מ 2K אז נלך רקורסיבית לתת העץ הימני. T דוגמא: K1 = 3, K2 = 10 3 4 6 7 8 10 Print_in_interval (T, K1, K2) if T is Null return if T.root > K1 Print_in_interval (T.left, K1, K2) if K1 ≤ T.root ≤ K2 print T.root if T.root < K2 Print_in_interval (T.right, K1, K2)
Question 4 T נתון עץ חיפוש בינארי T עם n קודקודים וגובה h. לכל צומת x יש שדה x.size אשר מחזיר את מספר הצמתים בתת העץ של x (כולל x עצמו). הציעו אלגוריתם למימוש פונקצייה Greater (T, k) שרץ בזמן O(h)אשר מקבל מפתח K ומחזיר מהו מספר המפתחות בעץ הנתון שגדולים מ . k T Greater ( 20 , k=19) answer is: 6 keys דוגמא: Greater ( 20 , k=19) 20 + 30 .size() + Greater ( 18 , k=19) Ø
Question 4 במקרה הגרוע, עברנו מהשורש עד לעלה בחיפוש אחר איבר עם מפתח K. נשים לב שבכל צומת שעברנו עליה, עושים מספר קבוע של פעולות. לכן במקרה הגרוע זמן ריצה חסום ע"י 𝑂 ℎ .
Question 5 נתונים שני עצי חיפוש בינאריים T1 וT2 עם גבהים h1 וh2 בהתאמה (הגבהים נתונים). נתון שכל הערכים בT1 קטנים ממש מכל הערכים בT2. הניחו שכל ערכי המפתחות שונים. כיצד ניתן לאחד את שני העצים לעץ אחד המכיל את איחוד הערכים בזמן O(min(h1,h2)), כך שגובה עץ האיחוד יהיה מינימלי ? מה יהיה גובה העץ המאוחד ? האם הגובה מינימלי ? T1 T2
Question 5 נתונים שני עצי חיפוש בינאריים T1 וT2 עם גבהים h1 וh2 בהתאמה (הגבהים נתונים). נתון שכל הערכים בT1 קטנים ממש מכל הערכים בT2. הניחו שכל ערכי המפתחות שונים. כיצד ניתן לאחד את שני העצים לעץ אחד המכיל את איחוד הערכים בזמן O(min(h1,h2)), כך שגובה עץ האיחוד יהיה מינימלי ? מה יהיה גובה העץ המאוחד ? T1 T2
Question 5
הציעו אלגוריתם הבודק אם עץ בינארי נתון הינו הוא BST. Question 6 הציעו אלגוריתם הבודק אם עץ בינארי נתון הינו הוא BST. הניחו שכל הערכים הינם מספרים שלמים שונים זה מזה הניחו שלכל קדקוד יש מצביע לשני הילדים אך לא מצביע להורה. הצעת פתרון: נבדוק בכל קדקוד בצורה רקורסיבית שערך הבן השמאלי קטן יותר מהערך הנוכחי וערך הבן הימני גדול יותר מהערך הנוכחי. האם הפתרון נכון ? דוגמא נגדית:
Question 6 פתרון (מתוקן): נשתמש בפונקציית עזר ששומרת את הגבולות העליונים והתחתונים של הערכים המורשים בתת-העץ −∞ ∞ 15 −∞ 15 8 8 15 20
Question 6 פתרון (מתוקן): נשתמש בפונקציית עזר ששומרת את הגבולות העליונים והתחתונים של הערכים המורשים בתת-העץ −∞ ∞ 15 −∞ 15 8 8 15 20
Question 6 פתרון (מתוקן): נשתמש בפונקציית עזר ששומרת את הגבולות העליונים והתחתונים של הערכים המורשים בתת-העץ −∞ ∞ 15 −∞ 15 15 ∞ 8 20 8 15 20 ∞ 10 30
Question 6 פתרון (מתוקן): נשתמש בפונקציית עזר ששומרת את הגבולות העליונים והתחתונים של הערכים המורשים בתת-העץ boolean isValid(Node root) { return isValidHelper(root, Integer.MIN_VALUE, Integer.MAX_VALUE) } boolean isValidHelper(Node curr, int min, int max) { if(curr.value < min || curr.value > max) return false if (curr.left != null && !isValidHelper(curr.left, min, curr.value)) if (curr.right != null && !isValidHelper(curr.right, curr.value, max)) return true } זמן הריצה הינו O(n). פתרון אפשרי נוסף הוא ביצוע הליכת Inorder ובדיקה שהיא ממוינת בסדר עולה. זמן ריצה O(n).