1 / 28

מבני נתונים

מבני נתונים. שיעור 2 - רקורסיה. מהי רקורסיה?. שיטה לפתרון בעיה ע"י חלוקת הבעיה לתתי בעיות הניתנות לפיתרון ע"י אותה השיטה...(??) במילים אחרות פונקציה שקוראת לעצמה... נשמע כמו מתכון בטוח ללולאה אינסופית?

Télécharger la présentation

מבני נתונים

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. מבני נתונים שיעור 2 - רקורסיה

  2. מהי רקורסיה? • שיטה לפתרון בעיה ע"י חלוקת הבעיה לתתי בעיות הניתנות לפיתרון ע"י אותה השיטה...(??) • במילים אחרות פונקציה שקוראת לעצמה... נשמע כמו מתכון בטוח ללולאה אינסופית? • אלגוריתמים רקורסיביים מתוכננים כך שלא ימשיכו עד אינסוף ע"י תנאים וקריאה רקורסיבית עם פרמטרים שונים בכל פעם.

  3. חישוב רקורסיבי של עצרת • חישוב עצרת: n!=1*2*3*…*n • פונקציה רקורסיבית המוגדרת כך: • שימו לב לשימוש בקריאה לאותה הפונקציה f, אך עם ערך שונה n-1 • במילים פשוטות: תגידו לי מה העצרת של n-1 ואני אדע לחשב את העצרת של n (ע"י מכפלה n*f(n-1))

  4. חישוב רקורסיבי של עצרת • אם כדי לחשב את העצרת של n אני צריך לדעת את העצרת של n-1 ואז n-2 וכך הלאה, מתי התהליך יפסק? ואיך החישוב ייתבצע בפועל? • הקוד הבא הינו פונקציה (שיטה) רקורסיבית לחישוב עצרת: intrFactorial(int n){ if (n==1) return 1; //תנאי בסיס else return n*rFactorial(n-1);//קריאה רקורסיבית }

  5. חלקי שיטה רקורסיבית • מקרה בסיס: ערכי קלט מסוימים שהפעלת השיטה עם ערכים אלו מחזירה ערך ללא קריאה רקורסיבית (זהו למעשה תנאי עצירה) • שיטה רקורסיבית חייבת להכיל לפחות מקרה בסיס אחד. • קריאה רקורסיבית: קריאה לאותה השיטה מתוכה. • ערכי הקלט שמועברים בקריאה הרקורסיבית חייבים להוביל לאחד ממקרי הבסיס.

  6. return 4 * 6 = 24 final answer call recursiveFactorial ( 4 ) return 3 * 2 = 6 call recursiveFactorial ( 3 ) return 2 * 1 = 2 call recursiveFactorial ( 2 ) return 1 * 1 = 1 call recursiveFactorial ( 1 ) return 1 call recursiveFactorial ( 0 ) תרשים המחשה

  7. Activation record n=3 n=2 long factorial (int n) { if (n<=1) return 1; else return n*factorial(n-1); } long factorial (int n) { if (n<=1) return 1; else return n*factorial(n-1); } n=1 long factorial (int n) { if (n<=1) return 1; else return n*factorial(n-1); }

  8. Activation record 6 n=2 n=3 long factorial (int n) { if (n<=1) return 1; else return n*factorial(n-1); } long factorial (int n) { if (n<=1) return 1; else return n*factorial(n-1); } 2 2*1 3*2 1 n=1 long factorial (int n) { if (n<=1) return 1; else return n*factorial(n-1); }

  9. פונקציה רקורסיבית • פונקציה רקורסיבית היא פונקציה שבתוך הגדרתה קוראת לעצמה. • פונקציה רקורסיבית מורכבת משני חלקים: • מקרה בסיסי )שהיא יודעת לפתור(. • מקרה מורכב שהיא יכולה לפרק לשני חלקים: • חלק אחד שהיא יודעת לפתור • חלק שני שהיא לא יודעת לפתור שהוא דומה לבעיה המקורית אבל פשוטה יותר. • תהליך פישוט הבעיה צריך להגיע למקרה בסיסי, אחרת הרקורסיה לא תיעצר. • הקושי – לפרק את הבעיה המורכבת לחלק שיודעים לפתור וחלק שהוא דומה לבעיה המקורית אבל פשוטה יותר!

  10. רקורסיה - דגשים • פונקציה רקורסיבית היא פונקציה שבתוך הגדרתה קוראת לעצמה. • רקורסיה אינסופית, להבדיל מלולאה אינסופית מסתיימת בשגיאה. • בכל רקורסיה חייב להיות תנאי עצירה. • כל עותק חדש של הפונקציה מקבל עותק חדש של המשתנים פנימיים שלו.

  11. רקורסיה לינארית • הצורה הכי פשוטה של רקורסיה היא רקורסיה לינארית. • ברקורסיה לינארית יש לכל היותר קריאה רקורסיבית אחת בכל פעם. • ייתכן ויהיו מספר אפשרויות לקריאות רקורסיביות, אך בכל הפעלה רק אחת מהאפשרויות תופעל. • כל האפשרויות לקריאות רקורסיביות חייבות להוביל למקרה בסיס.

  12. הפיכת סדר של מערך Algorithm ReverseArray(A, i, j): Input: An array A and nonnegative integer indices iand j מדוע צריך? Output: The reversal of the elements in A starting at index iand ending at j if i < j then Swap A[i] and A[ j] ReverseArray(A, i+ 1, j - 1) return A = 1,2,3,4,5,6,7,8,9,10 ReverseArray(A,0,9) = 10,9,8,7,6,5,4,3,2,1

  13. רקורסיה – מספרי פיבונאצ'י סידרת פיבונאצ'י: 0, 1, 1, 2, 3, 5, 8, 13, 21,…

  14. חישובים חוזרים של תתי בעיות! רקורסיה – מספרי פיבונאצ'י סידרת פיבונאצ'י: long fibonacci(int n) { if (n == 1 || n == 0) return n; else return fibonacci(n-1) + fibonacci(n-2); }

  15. סידרה של קריאות רקורסיביות f(3) f(2) f(1) return + return 1 return + f(1) f(0) return 1 return 0

  16. זמן ריצה לאלגוריתם פיבונאצ'י • Let nk denote number of recursive calls made by fibonacci(k). Then • n0 = 1 • n1 = 1 • n2 = n1 + n0 + 1 = 1 + 1 + 1 = 3 • n3 = n2 + n1 + 1 = 3 + 1 + 1 = 5 • n4 = n3 + n2 + 1 = 5 + 3 + 1 = 9 • n5 = n4 + n3 + 1 = 9 + 5 + 1 = 15 • n6 = n5 + n4 + 1 = 15 + 9 + 1 = 25 • n7 = n6 + n5 + 1 = 25 + 15 + 1 = 41 • n8 = n7 + n6 + 1 = 41 + 25 + 1 = 67. • Note that nk > 2k/2. It is exponential!

  17. המחשה לחישוב רקורסיבי של F7

  18. דוגמא מחלק גדול ביותר- GCD • הגדרה מתמטית: המחלק הגדול ביותר (GCD) של שני מספרים שלמים הינו המספר השלם הגדול ביותר שמחלק את שניהם ללא שארית. • בעיה: בהינתן m,nשלמים כך ש- , מצא את GCD שלהם.

  19. דוגמא מחלק גדול ביותר- GCD • הרעיון: אם m>n, אזי GCD(m,n) זהה ל- GCD(m-n,n). . • למה? אם m ו-n מתחלקים ב-d ללא שארית, אזי גם(m-n) מתחלקים ב-d ללא שארית. • לדוגמא: • m=80, n=24  GCD(80,24)=8 • 80=8*10, 24=8*3  80-24=8*(10-3)=8*7=56 • GCD(56,24)=8

  20. דוגמא מחלק גדול ביותר- GCD • מקרה בסיסי? • פיתרון של מקרה כללי?

  21. דוגמא מחלק גדול ביותר- GCD intgcd(int m, int n) { if(m == n) return m; else if (m > n) return gcd(m-n, n); else return gcd(m, n-m); } שימו לב כי אין פעולה על הערך המוחזר, פרט להעברתו. gcd(468, 24) gcd(444, 24) gcd(420, 24) ... gcd(36, 24) gcd(12, 24) (Now n is bigger) gcd(12, 12) (Same) 12

  22. רקורסיה או לולאות • כל בעיה שניתנת לפיתרון ע"י רקורסיה גם ניתנת לפיתרון ע"י לולאות, והוא יותר יעיל. • אבל קיימות בעיות שבטבען רקורסיביות ופתרון איטרטיבי הוא מאוד מסובך.

  23. ניתוח מקרה – מגדלי האנוי המטרה להעביר את כל הטבעות מעמוד A לעמוד C. ניתן להיעזר ב עמוד B. אסור להניח טבעת על טבעת קטנה ממנה! ע"פ אגדה הודית, נזירים עומלים יומם וליל על העברת 64 טבעות זהב וכשיסיימו העולם ייחרב... http://www.mazeworks.com/hanoi/index.htm

  24. הרעיון: אם נניח שאנחנו יודעים איך להעביר n-1 טבעות, נוכל לפתור את הבעיה עבור n

  25. אלגוריתם רקורסיבי לפתרון מגדלי האנוי • עבור n=1 העביר את הטבעת מ A ל C • העבר את n-1 הטבעות העליונות מ A ל B (העזר ב C) • העבר את הטבעת שנותרה (הכי גדולה) מ A ל C • העבר את n-1 הטבעות מ B ל C(העזר ב A)

  26. אלגוריתם רקורסיבי – מגדלי האנוי public class TowerofHanoi { void moveDisk(int count, int start, int finish, int temp) { if(count > 0) { moveDisks(count-1, start, temp, finish); System.out.print("Moving a disk from "+start+"to"+ finish); moveDisks(count-1, temp, finish, start); } } // End of MoveDisks() method -------------------------------------------- public static void main(String[] args) { int DISKS = 6; moveDisks(DISKS, 1, 3, 2); } // End of main() method } // End of TowerofHanoi class

  27. ניתוח סיבוכיות זמן הריצה • מספר הפעולות להזזת הדיסקיות: moves(n) = 1 if n = 1 moves(n) = 1 + 2 moves(n-1) if n <1 moves(n) = 1 + 2 moves (n-1) = 1 +2[1 + 2 moves (n-2)] = 1 +2[1 + 2 2[1 + 2 moves (n-3)]] = …………………………………… = 1 + 2 + 22 + 23 +………….+ 2n-1 = 20 + 21 + 22 + 23 +………….+ 2n-1 = 1(2n-1)/(2-1) = 2n-1 סכום סדרה הנדסית = O(2n)

  28. האם סוף העולם מתקרב? • הנזירים ההודים צריכים להעביר 64 דיסקיות. • מצאנו שסיבוכיות הזמן של האלגוריתם הוא O(2n). • אם נניח שהנזירים הזריזים מעבירים דיסקית בשניה • כלומר עבור 64 דיסקיות (n=64) נקבל T(64) = 264שזה יוצא...18446744073709551616 שניות • נחלק ב 60*60*24*365 = 31536000 כדי לעבור לשנים ונקבל...58,494,417,355 שנים. • נניח שהנזירים עובדים כבר כמה מאות שנים, עדיין אין מקום לדאגה!!

More Related