המצגת נטענת. אנא המתן

המצגת נטענת. אנא המתן

תרגול 11: רקורסיה ופיתוח טלסקופי

מצגות קשורות


מצגת בנושא: "תרגול 11: רקורסיה ופיתוח טלסקופי"— תמליל מצגת:

1 תרגול 11: רקורסיה ופיתוח טלסקופי
מבוא למדעי המחשב מ' - תירגול 11

2 מבוא למדעי המחשב - תרגול 11 ©
תוכנייה פתרון בעיות באמצעות רקורסיה ניתוח הסיבוכיות של אלגוריתמים רקורסיביים מבוא למדעי המחשב - תרגול 11 ©

3 מבוא למדעי המחשב - תרגול 11 ©
רקורסיה מבוא למדעי המחשב - תרגול 11 ©

4 רקורסיה רקורסיה הינה שיטה לתכנון אלגוריתמים, שבה הפתרון לקלט מסוים מתקבל על ידי פתרון אותה הבעיה בדיוק על קלט פשוט יותר, ובניית הפתרון עבור הקלט המורכב יותר מהפתרונות עבור הקלטים הפשוטים יותר. באופן מעשי, פונקציה רקורסיבית הינה פונקציה f() שתוך כדי ריצתה גורמת לקריאה חוזרת לעצמה. ברקורסיה ישירה הפונקציה f() מבצעת קריאה מפורשת לעצמה. ברקורסיה עקיפה הפונקציה f() קוראת לפונקציה אחרת g(), וזו קוראת בשלב מאוחר יותר ל-f().

5 רקורסיה מסביבנו

6 תרגיל 1: חישוב עצרת כתבו פונקציה שמקבלת מספר שלם ומחשבת את העצרת של המספר. תזכורת: n! = n(n-1)(n-2)...1, ומוגדר 0!=1 נראה פה קריאה רקורסיבית אילו היה לנו פתרון עבור הקלט n-1, איך היינו בונים פתרון עבור n? עבור איזה מקרה אנחנו כבר יודעים מה הפתרון?

7 תרגיל 1: פתרון מקרה הבסיס הוא n==0, שעבורו התוצאה ידועה.
מניחים שיש לנו פתרון על קלט קטן יותר, ובונים פתרון עבור הקלט הנוכחי unsigned long factorial(unsigned int n) { if (n == 0) return 1; return n * factorial(n-1); } מקרה הבסיס הוא n==0, שעבורו התוצאה ידועה. צעד המעבר מצמצם את הבעיה מ-n ל- n-1 , באמצעות הנוסחה n!=(n-1)!·n. קל לוודא שמכל n שמתחילים, תמיד מגיעים בסוף השרשרת למקרה הבסיס n==0, כיוון שאנו מקטינים בכל קריאה את n ב-1.

8 תמונת המחסנית ב-factorial()
x = factorial(2); factorial(2) factorial(n=2) { } if (n==0) return 1; return n * factorial(n-1); 2 factorial(1) factorial(2) if (n==0) return 1; return n * factorial(n-1); factorial(n=1) { } 1 1 factorial(0) factorial(1) factorial(2) factorial(n=0) { } if (n==0) return 1; return n * factorial(n-1); מבוא למדעי המחשב - תרגול 11 ©

9 תרגיל 1: פתרון unsigned long factorial(unsigned int n) {
if (n == 0) return 1; return n * factorial(n-1); }

10 תרגיל 1: הוספת תנאי עצירה מיותרים
unsigned long factorial(unsigned int n) { if (n == 0) return 1; if (n == 1) return 1; return n * factorial(n-1); }

11 תרגיל 1: הוספת תנאי עצירה מיותרים
unsigned long factorial(unsigned int n) { if (n == 0) return 1; if (n == 1) return 1; if (n == 2) return 2; return n * factorial(n-1); }

12 רקורסיה כדי לפתור בעיה באופן רקורסיבי ננסה לענות על השאלות:
אילו היה לנו פתרון עבור הבעיה על קלט "קטן" יותר (למשל, אם הקלט הוא מספר – מספר קטן יותר, אם הקלט הוא מערך – מערך קטן יותר), איך היינו יכולים לבנות פתרון עבור הקלט הנוכחי? עבור איזה קלט כבר לא צריך לפרק את הבעיה?

13 רקורסיה אלגוריתם רקורסיבי מורכב משני אלמנטים:
כאן מתבצעות הקריאות הרקורסיביות אלגוריתם רקורסיבי מורכב משני אלמנטים: מקרה הבסיס: זהו המקרה בקצה השרשרת הרקורסיבית בו הפתרון לבעיה כבר ידוע ואין צורך לפרק את הבעיה לתתי-בעיות. צעד המעבר: זהו האופן בו מפרקים את הבעיה הנתונה לתתי-בעיות זהות אך פשוטות יותר, ולאחר מכן בונים מהפתרונות שלהן את הפתרון של הבעיה המקורית.

14 גישה כללית לפתרון רקורסיבי
צורת מחשבה, כדי שנדע איזה חישובים לעשות בהינתן פיתרון לבעיה קטנה יותר בהינתן בעיה שרוצים לפתור: מצא דרך להקטין את הבעיה. הנח שהפונקציה יודעת לפתור את הבעיה המוקטנת. ומצא דרך לפתור את הבעיה הגדולה ע"י שימוש בפתרון של הבעיה המוקטנת – זה יהיה הצעד של הרקורסיה. מצא מהי הבעיה המוקטנת שאנחנו יודעים את הפתרון שלה – זה יהיה תנאי העצירה. מבוא למדעי המחשב - תרגול 11 ©

15 מבוא למדעי המחשב - תרגול 11 ©
תרגיל 2 כתבו פונקציה רקורסיבית שמציירת משולש בגובה n שורות: אילו ידענו להדפיס משולש בגובה n-1, איך יכולנו להשלים את הפתרון לקלט n? * ** *** **** ***** ****** ******* מבוא למדעי המחשב - תרגול 11 ©

16 תרגיל 2: פתרון הדפס משולש בגובה n-1. זו הקריאה הרקורסיבית.
void draw_triangle(int n) { int i; if (n <= 0) return; draw_triangle(n-1); for (i=0; i<n; ++i) putchar('*'); putchar('\n'); }

17 מפת הקריאות בהדפסת משולש
draw_triangle(3); 3 draw_triangle(3) { draw_trignle(2); putchar('*')... } *** * ** 1 2 draw_triangle(2) { draw_triangle(1); putchar('*')... } 2 3 1 draw_triangle(1) { draw_triangle(0); putchar('*')... } draw_triangle(0) { if (n==0) return; } מבוא למדעי המחשב - תרגול 11 ©

18 מבוא למדעי המחשב - תרגול 11 ©
ניתוח תהליך הרקורסיה ומה אם היינו רוצים את המשולש הפוך ? נשתמש באלגוריתם הרקורסיבי הבא: הדפס שורת כוכביות באורך n. הדפס משולש הפוך בגובה n-1. ******* ****** ***** **** *** ** * void draw_triangle(int n) { int i; if (n <= 0) return; for (i=0; i<n; ++i) putchar('*'); putchar('\n'); draw_triangle(n-1); } מבוא למדעי המחשב - תרגול 11 ©

19 מפת הקריאות בהדפסת משולש הפוך
draw_triangle(3); *** 1 draw_triangle(3) { putchar('*')... draw_triangle(2); } 1 ** 2 draw_triangle(2) { putchar('*')... draw_triangle(1) } 2 * 3 3 draw_triangle(1) { putchar('*')... draw_triangle(0) } draw_triangle(0) { if (n==0) return; } מבוא למדעי המחשב - תרגול 11 ©

20 תרגיל 3: סדרת פיבונאצ'י כתבו פונקציה שמקבלת מספר n ומחשבת את האיבר ה-n-י בסדרת פיבונאצ'י. תזכורת: סדרת פיבונאצ'י מתחילה מאיבר 0 שווה ל-0, מאיבר 1 ששווה ל-1 ומגדירה את האיבר ה-n להיות סכום שני האיברים הקודמים לו. נשים לב שהפתרון שלנו לבעיה עבור n מערב פתרון לבעיה עבור שני קלטים.

21 תרגיל 3: פתרון unsigned long fibonacci(unsigned int n) { if (n == 0) return 0; if (n == 1) return 1; return fibonacci(n-1) + fibonacci(n-2); } שימו לב שדרושים לנו כאן שני מקרי בסיס (עבור 0 וגם עבור 1), כיוון שהצעד הרקורסיבי שכתבנו מוגדר רק ל-n-ים החל מ-2. כיוון שצעד הרקורסיה כאן איננו פשוט כמו במקרה של עצרת, עלינו לוודא בקפדנות שלכל n שנתחיל ממנו, השרשרת אכן תסתיים תמיד באחד ממקרי הבסיס.

22 תמונת הקריאות ב-fibonacci()
כפי שניתן לראות, מספר הקריאות גדול מאוד ונעשים חישובים כפולים רבים. fibonacci(5) fibonacci(4) fibonacci(3) fibonacci(3) fibonacci(2) fibonacci(1) fibonacci(2) מומלץ לצייר את המחסנית גם במקרה הזה fibonacci(2) fibonacci(1) fibonacci(1) fibonacci(0) fibonacci(1) fibonacci(0) fibonacci(1) fibonacci(0) מבוא למדעי המחשב - תרגול 11 ©

23 מבוא למדעי המחשב - תרגול 11 ©
תרגיל 4- מיון רקורסיבי נתון מערך של int a בגודל n שברצוננו למיין. כתבו פונקציה רקורסיבית שמבצעת את המיון לפי העקרון העומד מאחורי bubble sort (היפוך הסדר בין איברים סמוכים שסדרם שגוי): מקרה הבסיס: עבור מערך בגודל 1 – אין צורך לבצע דבר. צעד המעבר, עבור מערך בגודל n>1: ממיינים רקורסיבית את המערך החל מהמקום השני בו. "מבעבעים" את האיבר הראשון למקומו הנכון. כלומר קוראים לפונקציה רקורסיבית על אותו המערך a 45 14 37 22 22 37 14 61 56 56 61 a+1 מבוא למדעי המחשב - תרגול 11 ©

24 מבוא למדעי המחשב - תרגול 11 ©
תרגיל 4- פתרון נוכל לכתוב פונקציה רקורסיבית שמממשת את המיון באופן פשוט למדי: void recursive_sort(int a[], int n) { int i; if (n <= 1) return; recursive_sort(a+1, n-1); for(i=0; (i<n-1) && (a[i]>a[i+1]); i++) { swap(a+i, a+i+1); } הערה: הפונקציה swap() מקבלת שני מצביעים ומחליפה את תוכנם. מבוא למדעי המחשב - תרגול 11 ©

25 מבוא למדעי המחשב - תרגול 11 ©
תרגיל 4- הדמיה a[n] void recursive_sort(int a[], int n) { int i=0; if (n <= 1) return; 45 37 22 14 61 56 a+1 45 14 22 37 56 61 recursive_sort(a+1, n-1); while(a[i] > a[i+1]) { swap(a+i, a+i+1); if ((++i) == n-1) break; } 14 22 37 45 56 61 מבוא למדעי המחשב - תרגול 11 ©

26 תרגיל 5- חיפוש מינימום במערך
הבעיה: יש למצוא את האיבר הקטן ביותר במערך של int בגודל n. הדרך הטבעית להקטין את הבעיה היא להקטין את גודל המערך באיבר אחד. נניח שאנחנו יודעים למצוא את המינימום במערך בגודל n-1. צעד: נמצא מינימום של תת מערך בלי האיבר הראשון: לדוגמה (n==5): או אם האיבר הראשון של המערך (בגודל n) קטן מהמינימום שמצאנו, אז האיבר הראשון הוא האיבר הקטן ביותר במערך. אחרת, האיבר הקטן ביותר במערך הוא המינימום שמצאנו. תנאי עצירה: עבור מערך בגודל 1, האיבר היחיד הינו גם האיבר הקטן ביותר במערך. min=2 min=2 6 7 3 2 9 1 5 9 2 4 min=2 min=1  1<2 1 4 9 2 min=2 min=2  6>2 6 7 3 2 9 min=9 9 min=4 4

27 תרגיל 5- פתרון int min(int a[], unsigned int n) { if (n == 1) {
return a[0]; } int minRest = min(a+1, n-1); if (a[0] < minRest) { else { return minRest; האם אפשר להחליף את n-1 ב n--? וב --n? מבוא למדעי המחשב - תרגול 11 ©

28 מבוא למדעי המחשב - תרגול 11 ©
סיבוכיות קוד רקורסיבי מבוא למדעי המחשב - תרגול 11 ©

29 ניתוח סיבוכיות של קוד רקורסיבי
נראה כעת שתי שיטות לחישוב סיבוכיות של קוד רקורסיבי: השיטה האיטרטיבית משמשת לחישוב סיבוכיות זמן של קוד רקורסיבי (ניתן להשתמש בה גם לחישוב סיבוכיות מקום אך אנו לא נדגים זאת). בשיטה זו בונים ביטוי רקורסיבי T(n) עבור זמן הפונקציה על קלט באורך n והופכים אותו לביטוי מפורש באמצעות הצבה חוזרת ונשנית. שיטת עץ הרקורסיה- משמשת לחישוב זמן ומקום של קוד רקורסיבי. בשיטה זו מציירים במפורש את עץ הקריאות של הרקורסיה ומחשבים את הסיבוכיות (זמן/מקום) של כל צומת בעץ בנפרד (ללא הקריאה הרקורסיבית). לאחר מכן סוכמים על פני הצמתים כדי לקבל את הסיבוכיות הכוללת. מבוא למדעי המחשב - תרגול 11 ©

30 סיבוכיות של factorial – השיטה האיטרטיבית
נסמן ב-T(n) את זמן הריצה של הפונקציה על קלט n ונבטא אותו ע"י התבוננות בקוד הפונקציה: unsigned long factorial(unsigned int n) { if (n == 0) return 1; return n * factorial(n-1); } במקרה שלנו, נקבל מקוד הפונקציה את הביטוי הבא, שמתאר את T(n) באופן לא מפורש (כאשר C הוא קבוע המציין את מספר הפעולות שמתבצעות בפונקציה ללא הקריאה הרקורסיבית): הקריאה factorial(n-1) לוקחת T(n-1) זמן, לפי הסימון שלנו מבוא למדעי המחשב - תרגול 11 ©

31 סיבוכיות של factorial – השיטה האיטרטיבית
לפי המשוואה הזו, אם נציב n-1 במקום n נקבל כי זמן הריצה עבור (n-1) מקיים: ערך זה ניתן להציב בחזרה בביטוי ל-T(n). נקבל: באופן דומה נוכל להמשיך ולהציב עבור n-2, n-3 וכן הלאה. מבוא למדעי המחשב - תרגול 11 ©

32 סיבוכיות של factorial – השיטה האיטרטיבית
נמשיך כך, ונקבל את הפיתוח של T(n): כאשר השורה התחתונה היא השורה ה-k בשיטה האיטרטיבית. מבוא למדעי המחשב - תרגול 11 ©

33 סיבוכיות של factorial – השיטה האיטרטיבית
שרשרת הפיתוח נעצרת כאשר מגיעים למקרה הבסיס. שימו לב שעבור מקרה זה, הביטוי שרשמנו בתחילה ל- T(n) איננו תקף. במקרה של factorial(), מקרה הבסיס הוא n=0, ולכן כאשר נגיע ל-T(0) בפיתוח נעצור. ובכן, מתי נגיע ל-T(0) בפיתוח? לשם כך נתבונן בביטוי שחישבנו עבור השורה ה-k בפיתוח: אנו רואים כי עבור ההצבה k=n (כלומר בשורה ה-n של הפיתוח) נקבל בדיוק T(0). נציב אם כך k=n בביטוי זה ונקבל: מבוא למדעי המחשב - תרגול 11 ©

34 סיבוכיות של factorial – השיטה האיטרטיבית
זהו, סיימנו! T(0) הוא מספר קבוע, כיוון שהוא איננו תלוי ב-n. לכן נוכל להחליפו בקבוע C1 (זהו למעשה מספר הפעולות הדרושות עבור הקלט n=0), ואנו מקבלים את הביטוי המפורש ל-T(n) : θ מציין חסם הדוק. כלומר זמן ריצת התוכנית הוא לא יותר ולא פחות מלינארי בקלט מבוא למדעי המחשב - תרגול 11 ©

35 מבוא למדעי המחשב - תרגול 11 ©
היפוך מחרוזת תרגיל: הפונקציה strflip() מקבלת מחרוזת ומחזירה אותה הפוכה (מהסוף להתחלה), אך מבצעת זאת רקורסיבית. נתחו את סיבוכיות הזמן של הפונקציה באמצעות השיטה האיטרטיבית. void strflip1(char *str) { if (*str == 0) return; strflip1(str+1); while (str[1] != 0) { swap(str,str+1); str++; } מבוא למדעי המחשב - תרגול 11 ©

36 היפוך מחרוזת – השיטה האיטרטיבית
void strflip1(char *str) { if (*str == 0) return; strflip1(str+1); while (str[1] != 0) { swap(str,str+1); str++; }

37 ניתוח סיבוכיות באמצעות ציור עץ הרקורסיה
נתבונן בפונקציה המבצעת חיפוש בינארי רקורסיבי: ננתח את סיבוכיות הזמן של הפונקציה כתלות בגודל המערך המועבר אליה, n, באמצעות ציור עץ הרקורסיה int BinarySearch(arr a,int x, int left, int right) { if(left>right) return -1; int middle=(left+right)/2; if(a[middle]==x) return middle; else if(x<a[middle]) return BinarySearch(a,x,left,middle-1); else return BinarySearch(a,x,middle+1,right); } מבוא למדעי המחשב מ' - תירגול 11

38 ניתוח הסיבוכיות של Binary Search
הציור משמאל הוא עץ הרקורסיה (או עץ הקריאות) של הפונקציה. כל עיגול בציור נקרא צומת והוא מייצג קריאה אחת בשרשרת הקריאות הרקורסיביות (כל צומת מייצג למעשה איבר נפרד על המחסנית). המספר הרשום בכל צומת הוא גודל הקלט עבור אותה קריאה. מכל צומת יוצאים חיצים כלפי מטה לכל הקריאות הרקורסיביות אותן הוא מבצע. הצמתים אליהם יש חץ נקראים הבנים של הצומת. במקרה של חיפוש בינארי יש רק קריאה רקורסיבית אחת ולכן לכל צומת יש רק בן אחד (במקרה הכללי אכן עלול להיווצר מעין עץ הפוך) ... מבוא למדעי המחשב מ' - תירגול 11

39 ניתוח הסיבוכיות של Binary Search
מבוא למדעי המחשב - תרגול 11 ©

40 ניתוח הסיבוכיות של Binary Search
... בציור סימנו כל צומת בגודל הקלט שהוא מקבל: תחילה מקבלים מערך בגודל n, בקריאה הבאה מצמצמים אותו בחצי, וכן הלאה. איך נחלץ את סיבוכיות הזמן והמקום מהציור? מבוא למדעי המחשב מ' - תירגול 11

41 ניתוח הסיבוכיות של Binary Search
... סיבוכיות הזמן של הריצה מתקבלת ע"י סכימת זמני כל הצמתים. במקרה הזה מספר הצמתים שווה לעומק העץ, שמסומן כרגע כ-k עומק עץ = מרחק מהצומת העליון עד לצומת הנמוך ביותר מבוא למדעי המחשב מ' - תירגול 11

42 ניתוח הסיבוכיות של Binary Search
... עומק העץ בקריאות רקורסיביות שווה למספר הקריאות שצריך לבצע עד שמגיעים למקרה בסיס. במקרה של חיפוש בינארי – עד שמגיעים למערך בגודל 1. כלומר במקרה הבסיס מתקיים ש- נעביר אגפים ונחלץ את k: logn צמתים מבוא למדעי המחשב מ' - תירגול 11

43 ניתוח הסיבוכיות של Binary Search
... סיבוכיות זמן: ישנם צמתים, כאשר כל אחד לוקח C זמן. לכן סיבוכיות הזמן היא כדי לחשב סיבוכיות מקום, עלינו לחלץ את כמות הזיכרון המקסימלית שאנחנו צריכים בו-זמנית. מבוא למדעי המחשב מ' - תירגול 11

44 ניתוח הסיבוכיות של Binary Search
... כל קריאה צריכה כמות זכרון קבועה אולם יש לקחת בחשבון כי הזכרון שתופסת כל קריאה אינו משתחרר ברגע שקוראים לקריאה הבאה, אלא הוא נצבר על המחסנית! כמות הזכרון הכי גדולה שנתפסת בתכנית בו זמנית היא כאשר המחסנית הכי מלאה, כלומר בתחתית העץ, בקריאה הרקורסיבית האחרונה. במצב זה יש לנו קריאות פתוחות, כאשר כל אחת צורכת זכרון. logn צמתים מבוא למדעי המחשב מ' - תירגול 11

45 ניתוח הסיבוכיות של Binary Search
... לכן סך כל הזכרון שאנחנו זקוקים לו בו זמנית בריצה הוא וסיבוכיות הזכרון היא logn צמתים מבוא למדעי המחשב מ' - תירגול 11

46 ניתוח אלגוריתם Merge Sort
מערך בגודל 1 או פחות תמיד ממויין. merge_sort(A[N]) { if (N <= 1) return; allocate tmp[N]; merge_sort( A[0..N/2] ); merge_sort( A[N/2+1..N-1] ); tmp = merge( A[0..N/2], A[N/2+1..N-1] ); memcpy(A  tmp); } נקצה מערך כגודל המערך שעלינו למיין. נמיין את האיברים בחצי הראשון במערך. נמיין את האיברים בחצי השני במערך. נמזג את חצי המערכים ונשמור את התוצאה ב-tmp. נעתיק חזרה מ-tmp ל-A את המערך הממויין. מבוא למדעי המחשב - תרגול 11 ©

47 ניתוח אלגוריתם Merge Sort
נצייר את עץ הרקורסיה: בכל איטרציה מבצעים שתי קריאות רקורסיביות, כל אחת עם קלט קטן בחצי: ... מבוא למדעי המחשב מ' - תירגול 11

48 סיבוכיות הזמן של Merge Sort
בכל פעם שנכנסים לתוך קריאה רקורסיבית, אורך המערך קטן פי 2. לכן, העומק המקסימאלי של הרקורסיה הוא Θ(log(n)) , כפי שראינו בדוגמה הקודמת. לניתוח זמן הריצה נסמן כמה זמן לוקח כל צומת (ללא הקריאה הרקורסיבית) ונסכום. בכל ריצה אנחנו מבצעים merge והעתקה של מערך בגודל הקלט שקיבלנו, לכן עבור צומת עם קלט m מתבצעות פעולות. מבוא למדעי המחשב - תרגול 11 ©

49 מבוא למדעי המחשב מ' - תירגול 11
מה סכום הצמתים בעץ? אפשר לראות שבכל קומה של העץ, מספר הצמתים מוכפל. כלומר בקומה ה-k יש לנו צמתים, כאשר כל צומת לוקח זמן. לכן כל קומה לוקחת זמן. ... מבוא למדעי המחשב מ' - תירגול 11

50 מבוא למדעי המחשב מ' - תירגול 11
... מספר הקומות הוא כעומק העץ לכן סה"כ זמן הריצה הוא מבוא למדעי המחשב מ' - תירגול 11

51 סיבוכיות המקום של Merge Sort
עלינו למצוא את כמות הזכרון המקסימלית שתפוסה בו-זמנית. נשים לב שהקריאות הרקורסיביות קורות אחת אחרי השניה: merge_sort(A[N]) { if (N <= 1) return; allocate tmp[N]; merge_sort( A[0..N/2] ); merge_sort( A[N/2+1..N-1] ); tmp = merge( A[0..N/2], A[N/2+1..N-1] ); memcpy(A  tmp); } מבוא למדעי המחשב מ' - תירגול 11

52 סיבוכיות המקום של Merge Sort
כלומר כל צומת קורא לבן הראשון ורק אחרי שהבן הראשון מסיים לרוץ, הוא קורא לבן השני. לכן המספר הגדול ביותר של קריאות שפתוחות בו"ז הוא כעומק העץ. כל קריאה עם קלט בגודל זקוקה ל זכרון, לכן סה"כ הזכרון הדרוש הוא ... מסלול קריאות לדוגמה מבוא למדעי המחשב מ' - תירגול 11

53 מבוא למדעי המחשב - תרגול 11 ©
שאלות ממבחנים מבוא למדעי המחשב - תרגול 11 ©

54 שאלות ממבחנים – חורף 2013 מועד א'
חשבו את סיבוכיות הזמן והמקום של הפונקציה f. void aux(int n) { int m=0; for (int i=0; i<n; ++i) { m += i; } printf("%d\n", m); int func(int n) if (n < 2){ return 0; aux(func(n/2)); return n; מבוא למדעי המחשב מ' - תירגול 4

55 שאלות ממבחנים – חורף 2013 מועד א'
int func(int n) { if (n < 2){ return 0; } aux(func(n/2)); return n; נשים לב ש-func על פרמטר n מחזירה בסופו של דבר n. כלומר aux(func(n/2)) שקול מבחינת פרמטרים ל-aux(n/2). לכן, כל צומת ברקורסיה של func לוקח זמן קבוע + הזמן שלוקח ל- aux(n/2) לרוץ. מבוא למדעי המחשב מ' - תירגול 11

56 שאלות ממבחנים – חורף 2013 מועד א'
void aux(int n) { int m=0; for (int i=0; i<n; ++i) { m += i; } printf("%d\n", m); נשים לב שהסיבוכיות של aux היא על פרמטר n מבוא למדעי המחשב מ' - תירגול 11

57 מבוא למדעי המחשב מ' - תירגול 11
... סכום הצמתים הוא: ומתקיים: לכן סיבוכיות הזמן היא וכפי שניתן לראות עומק העץ הוא ומכיוון שאין זכרון נוסף התלוי בגודל הקלט, סיבוכיות הזכרון היא מבוא למדעי המחשב מ' - תירגול 11

58 שאלות ממבחנים – אביב 2011 מועד א'
חשבו את סיבוכיות הזמן והמקום של הפונקציה f. char g(char *s, int n) } int i; char t; for (i = 0; i < n/2; i++) { t = *(s + i); *(s+i) = s[n-1-i]; *(s+n-1-i) = t; { return f(s, n); char f(char *s, int n) { if (n == 1) return *s; return g(s, n-1); מבוא למדעי המחשב מ' - תירגול 11

59 שאלות ממבחנים – אביב 2011 מועד א'
נבדיל בין סוגי הצמתים ונשים לב שמבחינת הרקורסיה, רק הפרמטר n משנה. צמתי g נקראים מצמתי f וקוראים לצמתי f מבלי לשנות את פרמטר n. לפני הקריאה מבצעת לולאה שלוקחת n/2 זמן. לכן צמתי g ייראו כך: char g(char *s, int n) } int i; char t; for (i = 0; i < n/2; i++) { t = *(s + i); *(s+i) = s[n-1-i]; *(s+n-1-i) = t; { return f(s, n); מבוא למדעי המחשב מ' - תירגול 11

60 שאלות ממבחנים – אביב 2011 מועד א'
צמתי f מורידים את הפרמטר n באחד בקריאה ל- g, ולפני כן מבצעים מספר קבוע של פעולות. לכן צמתי f ייראו כך, כאשר מתחת צומת g: char f(char *s, int n) { if (n == 1) return *s; return g(s, n-1); מבוא למדעי המחשב מ' - תירגול 11

61 מבוא למדעי המחשב מ' - תירגול 11
... סיבוכיות מקום: עומק העץ סיבוכיות זמן: צמתי f צמתי g מבוא למדעי המחשב מ' - תירגול 11


הורד את "ppt "תרגול 11: רקורסיה ופיתוח טלסקופי

מצגות קשורות


מודעות Google