390 likes | 663 Views
תרגול 5. Trees, BSTs - עצים ועצי חיפוש בינאריים. Tree - עץ. ADT that stores elements hierarchically. With the exception of the root, each node in the tree has a parent and zero or more children nodes. Access methods in the tree ADT: root() – returns the root of the tree
E N D
תרגול 5 Trees, BSTs- עצים ועצי חיפוש בינאריים
Tree - עץ • ADT that stores elements hierarchically. • With the exception of the root, each node in the tree has a parent and zero or more children nodes. • Access methods in the tree ADT: • root() – returns the root of the tree • parent(node v) – returns the parent of node v • children(node v) – returns an iterator of the children of node v. • depth(node v) • The depth of node v = the number of ancestors of v • depth(root) = 0 • depth(v ≠ root) = depth(v.parent) + 1 • height(node v) • The maximum height of a node v in T • height(v) = 0 , if v is a leaf • height(v) = 1 + maximum-height of a child of v, if v is not a leaf. • height() • The height of the root of T
Binary Tree – עץ בינארי • Each node has at most two children, left-son and right-son. • Full Binary Tree – A binary tree in which each node has exactly zero or two children • A full binary tree with n leaves has n-1 inner nodes. • Complete Binary Tree- A binary tree in which every level, except possibly the deepest, is completely filled. At depth n, the height of the tree, all nodes must be as far left as possible. • A complete binary tree of height h has between 2h and 2h+1-1 nodes. • The height of a complete binary tree with n nodes is
הליכות בעץ בינארי • Inorder– inorder on the left sub tree, visit the current node and finally, inorder on the right sub tree. 15 Write current node Rec. call on left child 7 8 Rec. call on right child 3 12 13 Return 7, 15, Inorder: 3, 8, 12, 13
הליכות בעץ בינארי • Preorder – visit the current node, preorder on its left sub tree and finally, preorder on its right sub tree. 15 Write current node Rec. call on left child 7 8 Rec. call on right child 3 12 13 Return Preorder: 3, 12, 13 8, 15, 7,
הליכות בעץ בינארי • Postorder - postorder on the left sub tree, postorder on the right sub tree and finally, visit the current node. 15 Rec. call on right child Rec. call on left child 7 8 Write current node and Return 3 12 13 7, 15 Postorder: 3, 12, 13, 8,
k-Tree • Each node has k children at most. • Representation option: “left child - right sibling”, • each node has the following pointers: • parent • left child - a pointer to the left most child. • right-sibling - a pointer to the next sibling on the right.
תרגיל 3 שחזרו את העץ הבינארי T מההליכות Preorder וInorder הנתונות שלו: Preorder: a,b,c,d,e,g,h,j,f. Inorder: c,d,b,a,h,g,j,e,f.
תרגיל 3 שחזרו את העץ הבינארי T מההליכות Preorder וInorder הנתונות שלו: Preorder: a,b,c,d,e,g,h,j,f. Inorder: c,d,b,a,h,g,j,e,f. לפני השורש – תת-עץ שמאלי אחרי השורש – תת-עץ ימני שורש העץ
תרגיל 3 שחזרו את העץ הבינארי T מההליכות Preorder וInorder הנתונות שלו: Preorder: a,b,c,d,e,g,h,j,f. Inorder: c,d,b,a,h,g,j,e,f. לתת-עץ b,c,d אנחנו יודעים את ההליכות Preorder וInorder כיוון שהן ההליכות המושרות מT: Preorder: b,c,d. Inorder: c,d,b.
תרגיל 3 שחזרו את העץ הבינארי T מההליכות Preorder וInorder הנתונות שלו: Preorder: a,b,c,d,e,g,h,j,f. Inorder: c,d,b,a,h,g,j,e,f. לתת-עץ b,c,d אנחנו יודעים את ההליכות Preorder וInorder כיוון שהן ההליכות המושרות מT: Preorder: b,c,d. Inorder: c,d,b.
תרגיל 3 שחזרו את העץ הבינארי T מההליכות Preorder וInorder הנתונות שלו: Preorder: a,b,c,d,e,g,h,j,f. Inorder: c,d,b,a,h,g,j,e,f. Preorder: e,g,h,j,f. Inorder: h,g,j,e,f.
תרגיל 3 שחזרו את העץ הבינארי T מההליכות Preorder וInorder הנתונות שלו: Preorder: a,b,c,d,e,g,h,j,f. Inorder: c,d,b,a,h,g,j,e,f. טענה: משני הילוכים שונים בעץ T, כאשר אחד מהם הוא Inorder, ניתן לשחזר את העץ. אחת הדרכים להוכיח טענה זו היא ע"י שימוש בתהליך בו השתמשנו לפתרון התרגיל.
תרגיל 4 • האם תמיד ניתן לשחזר עץ בינארי מהליכות הPreorderוהPostorder שלו? • הוכיחו את הטענה או תנו דוגמא נגדית פתרון: לא תמיד דוגמא:Preorder: AB Postorder: BA ישנן שתי אפשרויות לעץ:
תרגיל 1 • לעץ בינארי T נגדיר • L(T) – מספר העלים בעץ T • D2(T) – מספר הקודקודים בT עם דרגה 2 (2 ילדים בדיוק) הוכיחו שבכל עץ בינארי T עם nקודקודים מתקיים D2(T)=L(T)-1 הערה: בעץ בינארי מלא (Full) מספר העלים הוא מספר הקודקודים הפנימיים + 1 פתרון: הוכחה באינדוקציה על מספר הקודקודים בעץ. מקרה בסיס: n=1, L(T)=1, D2(T)=0
תרגיל 1 הוכחה באינדוקציה על מספר הקודקודים בעץ. • צעד האינדוקציה: נניח שהטענה נכונה לכל k<n • נסתכל על השורש בעץ עם nקודקודים • 2 מקרים אפשריים: מקרה ראשון: דרגת השורש היא 1. • ל TולT1 יש אותו מספר עלים • ל TולT1 יש אותו מספר קודקודים עם דרגה 2 T1 הנחת האינדוקציה 2 1
תרגיל 1 הוכחה באינדוקציה על מספר הקודקודים בעץ. • צעד האינדוקציה: נניח שהטענה נכונה לכל k<n • נסתכל על השורש בעץ עם nקודקודים • 2 מקרים אפשריים: מקרה שני: דרגת השורש היא 2. • מספר העלים ב Tהוא סכום העלים בT1 ובT2 • מספר הקודקים עם דרגה 2 ב Tהוא סכום הקודקודים עם דרגה 2 בT1 ובT2ועוד קודקוד 1 (השורש) T1 T2 ע"פ 2 ע"פ הנחת האינדוקציה ע"פ 1
תרגיל 2 • T עץ בינארי עם nקודקודים. לכל קודקודx יש את השדות הבאים: • x.key – מספר טבעי • x.left – מצביע לבן השמאלי • x.right – מצביע לבן הימני • x.val – מספר טבעי לשימוש כללי (אינו בשימוש בT במקור) • נגדיר את maxPath(T) כסכום המקסימלי של מפתחות במסלול (פשוט) מהשורש לעלה כלשהו. • נגדיר Path(T) כמסלול כלשהו עם סכום זה. • דוגמא: maxPath(T)=23 Path(T) = left, left
תרגיל 2 • T עץ בינארי עם nקודקודים. לכל קודקודx יש את השדות הבאים: • x.key – מספר טבעי • x.left – מצביע לבן השמאלי • x.right – מצביע לבן הימני • x.val – מספר טבעי לשימוש כללי (אינו בשימוש בT במקור) • נגדיר את maxPath(T) כסכום המקסימלי של מפתחות במסלול (פשוט) מהשורש לעלה כלשהו. • נגדיר Path(T) כמסלול כלשהו עם סכום זה. • תארו אלגוריתם למציאת הערך maxPath(T) בזמן O(n) • כיצד ניתן לשנות את האלגוריתם כך שגם ידפיס את המסלול המקסימלי?
תרגיל 2 • תארו אלגוריתם למציאת הערך maxPath(T) בזמן O(n) • כיצד ניתן לשנות את האלגוריתם כך שגם ידפיס את המסלול המקסימלי? פתרון: • מחשבים רקורסיבית את maxPathשל הבן השאמלי וכן את maxPath של הבן הימני, ומוסיפים את המפתח של הקודקוד למקסימלי מביניהם
תרגיל 2 • תארו אלגוריתם למציאת הערך maxPath(T) בזמן O(n) • כיצד ניתן לשנות את האלגוריתם כך שגם ידפיס את המסלול המקסימלי? פתרון: • נחשב את maxPathכמו קודם, רק שנעדכן את x.val ל0 אם הסכום המקסימלי בא מתת-עץ השמאלי ו1 אם מהשמאלי. בהדפסת המסלול נשתמש בערך x.val להחליט לאיזה כיוון להמשיך.
תרגיל 2 • תארו אלגוריתם למציאת הערך maxPath(T) בזמן O(n) • כיצד ניתן לשנות את האלגוריתם כך שגם ידפיס את המסלול המקסימלי? ניתוח זמן: • מבקרים בכל קודקוד פעם אחת, לכן זמן הריצה O(n) • מבקרים פעם אחת בכל קודקוד במסלול, ומספר הקודקודים במסלול חסום ע"י n. לכן סה"כ O(n)
Binary Search Tree – עץ חיפוש בינארי הדגמת מחיקות מעץ חיפוש בינארי: 15 20 8 23 3 12 13 10 11
Binary Search Tree – עץ חיפוש בינארי הדגמת מחיקות מעץ חיפוש בינארי: 15 20 8 3 12 13 23 10 11
תרגיל 5 נתון BSTT בגודל n, בו לכל קודקודx יש שדה נוסף של x.size – מספר המפתחות של תת-העץ של x (כולל x עצמו) הציעו אלגוריתם בזמן O(h) (כאשר h גובה העץ) למימוש Greater(T,k)– מציאת מספר המפתחות שממש גדולים מk הדגמה: k = 10 key=15 size= 36 הקודקוד Greater(T,k)=15+1+4=20 key=20 size= 15 key=8 size= 20 כל תת-העץ כל תת-העץ key=4 size= 11 key=10 size= 8 key=12 size= 4
תרגיל 5 נתון BSTT בגודל n, בו לכל קודקודx יש שדה נוסף של x.size – מספר המפתחות של תת-העץ של x (כולל x עצמו) הציעו אלגוריתם בזמן O(h) (כאשר h גובה העץ) למימוש Greater(T,k)– מציאת מספר המפתחות שממש גדולים מk פתרון: זמן ריצה:O(h) הערה:h=O(n) במקרה הגרוע ביותר, וO(logn) במקרה הממוצע
תרגיל 6 נתון עץ חיפוש בינארי T עם גובה h שמכיל קודקוד עם ערך aוקודקוד עם ערך b. מצאו אלגוריתם שמחזיר את כל המפתחות בטווח [a,b] (a<b) בזמן O(h+k), כאשר k מספר המפתחות בטווח.
תרגיל 6 פתרון: • Range(a, b) • Find nodes containing a and b in the tree, let Pa and Pb be the search path from the root to a and b respectively. • Let x be the node where Pa and Pb split. • For every node v in the search path from a to x do:if (a < v){ print v;inorder(v.right);} • For every node v in the search path from x to b do: if (b > v){inorder(v.left); print v; }
תרגיל 7 • נתונים שני עצי חיפוש בינאריים T1וT2 עם גבהים h1 וh2 בהתאמה (h1 וh2נתונים). • נתון בנוסף שכל הערכים בT1 קטנים ממש מכל הערכים בT2. הניחו שכל ערכי המפתחות שונים. • כיצד ניתן לאחד את שני העצים לעץ אחד המכיל את איחוד הערכים בזמן O(min(h1,h2)), כך שגובה עץ האיחוד יהיה O(max(h1,h2))? • מה יהיה גובה עץ האיחוד?
תרגיל 7 • כיצד ניתן לאחד את שני העצים לעץ אחד המכיל את איחוד הערכים בזמן O(min(h1,h2)), כך שגובה עץ האיחוד יהיה O(max(h1,h2))? פתרון: case a: h1 ≤ h2 Extract from T1 the element v with the maximum key in T1 in O(h1) time. v.left ← T1 v.right ← T2 v is the root of the new merged tree. T1 T2 max(T1)
תרגיל 7 • כיצד ניתן לאחד את שני העצים לעץ אחד המכיל את איחוד הערכים בזמן O(min(h1,h2)), כך שגובה עץ האיחוד יהיה O(max(h1,h2))? פתרון: case a: h1 ≤ h2 Extract from T1 the element v with the maximum key in T1 in O(h1) time. v.left ← T1 v.right ← T2 v is the root of the new merged tree. case b: h1 > h2 Extract from T2 the element v with the minimum key in T2 in O(h2) time. v.left ← T1 v.right ← T2 v is the root of the new merged tree. T1 T2 min(T2)
תרגיל 7 • מה יהיה גובה עץ האיחוד? פתרון:max(h1,h2)+1
תרגיל 8 • מצאו אלגוריתם הבודק אם עץ בינארי נתון T הוא BST. • הניחו שכל הערכים הינם מספרים שלמים שונים זה מזה • הניחו שלכל קודקוד יש מצביע לשני הילדים אך לא מצביע להורה. פתרון (שגוי): נבדוק בכל קודקוד בצורה רקורסיבית שערך הבן השמאלי קטן יותר מהערך הנוכחי וערך הבן הימני גדול יותר מהערך הנוכחי. פתרון זה אינו מספיק – מצאו דוגמא נגדית
תרגיל 8 פתרון (שגוי): נבדוק בכל קודקוד בצורה רקורסיבית שערך הבן השמאלי קטן יותר מהערך הנוכחי וערך הבן הימני גדול יותר מהערך הנוכחי. פתרון זה אינו מספיק – מצאו דוגמא נגדית 15 8 20
תרגיל 8 פתרון (מתוקן): נשתמש בפונקציית עזר ששומרת את הגבולות העליונים והתחתונים של הערכים המורשים בתת-העץ booleanisValid(Node root) { return isValidHelper(root, Integer.MIN_VALUE, Integer.MAX_VALUE) } booleanisValidHelper(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)) return false if (curr.right != null && !isValidHelper(curr.right, curr.value, max)) return false return true } זמן הריצה הינו O(n). פתרון אפשרי נוסף הוא מציאת הליכת הInorder ובדיקה שהיא ממוינת. זמן ריצה O(n).
שאלות נוספות (אם יש זמן) • הוכיחו או הפריכו את הטענות הבאות • הקודקוד הראשון בסדר הליכת Preorder הוא הקודקוד האחרון בסדר הליכת Postorder. • הקודקוד במיקום ה i בסדר הליכת Preorder הוא הקודקוד במיקום ה (n+1-i) בסדר הליכת Postorder. • לכל קודקודv במסלול מהשורש לעלה בעץ T מתקיים Height(v)+Depth(v)=Height(T) • בעץ חיפוש בינארי, אם לשורש יש שני ילדים, אז המסלול של maxPath עובר דרך הבן הימני. • בעץ חיפוש בינארי תמיד ניתן לשחזר את העץ מידיעת סדר הליכת הPreorder בלבד. הארוך ביותר