רקורסיה...

sivan83

New member
רקורסיה...

שלום לכם.... אני לומדת באונברסיטה מבוא לתכנות, ואנו לומדים את שפת java . קצב הלימוד מטורף והמרצה רץ עם החומר ולא הבנתי טוב את הנושא של הרקורסיה.... והוא נתן עבודת הגשה בכלל לא פשוטה שאת כולה צריך לעשות ברקורסיה..... איך מתחילים בכלל?!?!? מישהו יכול להפנות אותי לחומר עזר בנושא שמסביר בצורה טובה מה זה אומר בכלל רקורסיה? עם דוגמאות או תרגילים ברורים ??? האם אפשר לעשות טבלאות מעקב דרך התוכנית של eclipse או jcreator כדי להבין איך מתנהלת הרקורסיה??? תודה לכל המשיבים...
 

orennahum

New member
דוגמאות והסברים

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

DadleFish

New member
אכן בעיה

רקורסיה היא נושא מאוד לא פשוט, שהרבה מאוד אנשים מתקשים בו בהתחלה. מאוד לא טבעי לחשוב על רקורסיה ולכן הבלבול, אבל אני יכול לנחם אותך בכך שככל שתעבדי על זה יותר ותראי יותר דוגמאות, כך ישתפר מצבך ותצליחי להבין יותר טוב, עד שבסוף תגיעי למצב שרקורסיה תהיה מאוד פשוטה עבורך. בכל מקרה, לשאלתך - כן, אפשר לעבוד עם eclipse או עם כל סביבה אחרת כדי להבין "מה קורה". ניקח את הדוגמה הקלאסית והפשוטה ביותר - עצרת. עצרת של מספר n מוגדרת כך:
n!=1*2*...*(n-1)*n​
אבל אפשר להגדיר את זה בצורה שונה:
n!=(n)*(n-1)!​
כלומר, התוצאה של !n היא מכפלה של n בתוצאה של !(n-1). נכון? נכון. זה לא קשור לתכנות, זו פשוט מתימטיקה. עכשיו, אם הייתי נותן לך פונקציה שיודעת לחשב את !(n-1), היית יודעת לחשב את !n בקלות, נכון? ואיך היית מחשבת את !(n-1)? אה... בשביל זה הייתי נותן לך פונקציה נוספת שיודעת לחשב את !(n-2), ואז היית מכפילה את התוצאה של הפונקציה הזו ב-(n-1) והיית מקבלת בסה"כ את !(n-1). אם לא עקבת אחריי ואת מבולבלת, תקראי שוב עד שתביני. ככה התהליך ממשיך ל-n-3 ואז ל-n-4 וכן הלאה. מתי תעצרי? שימי לב שבסוף את יורדת עד ל-(n-(n-1, שזה בעצם 1. מה התוצאה של !1? את זה את יודעת - זה 1. ולכן במקרה הספציפי הזה, את תחזירי 1. ננסח את זה ככה: בואי נכתוב פונקציה שמבקשים ממנה את התוצאה של !n, והיא מחזירה את !(n*(n-1. זה יעבוד, נכון? יפה. רק מה שחסר פה זה את תנאי העצירה, שהוא - נכון - n==1. במקרה הזה נחזיר פשוט - 1. עכשיו תראי את הקוד:
public class Recursion { static int atzeret(int n) { if (n==1) { return 1; } else { return (n*atzeret(n-1)); } } public static void main(String[] args) { System.out.println(atzeret(10)); } }​
הגדרתי פה פונקציה שנקראת atzeret, והיא עושה בדיוק את מה שהבטחתי. אם n הוא 1, היא תחזיר פשוט 1. אם לא, היא תחזיר את n כפול התוצאה של atzeret על n-1. בנוסף לתוכנית הזו, הכנתי תוכנית זהה עם קצת הדפסות DEBUG, והפלט שלה מאוד מעניין, שימי לב:
Atzeret called with 10 .Atzeret called with 9 ..Atzeret called with 8 ...Atzeret called with 7 ....Atzeret called with 6 .....Atzeret called with 5 ......Atzeret called with 4 .......Atzeret called with 3 ........Atzeret called with 2 .........Atzeret called with 1 ........Atzeret returned with the result of 1 .......Atzeret returned with the result of 2 ......Atzeret returned with the result of 6 .....Atzeret returned with the result of 24 ....Atzeret returned with the result of 120 ...Atzeret returned with the result of 720 ..Atzeret returned with the result of 5040 .Atzeret returned with the result of 40320 Atzeret returned with the result of 362880 The result of atzeret(10) is 3628800​
שימי לב מה קורה. קראנו ל-(atzeret(10. היא יורדת פנימה ל-9, שיורדת פנימה ל-8, שיורדת פנימה ל-7, וככה עד הירידה ל-1. הקריאה ל-1 חוזרת מייד בתוצאה 1. כעת מכפילים את 1 במספר הנוכחי - אם תעקבי באופן אנכי אחרי הנקודות, תראי שהמספר הנוכחי הוא 2. התוצאה שתחזור היא 2*1. היא תחזור כמובן ל-(atzeret(3 שתוסיף את ההכפלה ב-3, לתוצאה כוללת של 6, שתחזור ל-(atzeret(4, שתכפיל ב-4 לתוצאה של 24, וכו'. ככה אנחנו חוזרים בקריאות אחורה עוד ועוד, עד שמגיעים ל-!10. את יכולה גם לעקוב אחרי המתרחש עם DEBUGGER, ואם יש לך שאלות נוספות, תשאלי. בין הדוגמה הזו של עצרת לבין חשיבה בצורה רקורסיבית יש עוד זמן רב, אבל תחשבי על זה גם ככה - כשאני הופך חולצה, אני מכניס את היד עד לסוף השרוול, תופס אותו בקצה ומושך אותו בחזרה. תנסי לחשוב בצורה כזו. לפעמים את צריכה לרוץ ברשימה מקושרת, נגיד, עד הסוף ואז לחזור את כל הדרך אחורה, כשבדרך את נעזרת בעובדה שאת חוזרת. הנה התוכנית עם הודעות ה-DEBUG, את יכולה להריץ אותה ולבדוק:
public class Recursion { static int level; static int atzeret(int n) { for (int i=0; i < level; i++) { System.out.print("."); } System.out.println("Atzeret called with " + n); if (n==1) { return 1; } else { level = level + 1; // Because we're going deeper now int result = atzeret(n-1); level = level - 1; // Because we have returned up for (int i=0; i < level; i++) { System.out.print("."); } System.out.println("Atzeret returned with the result of " + result); return (n*result); } } public static void main(String[] args) { level = 0; int result = atzeret(10); System.out.println("The result of atzeret(10) is " + result); } }​
 

codec

New member
נראה לי זה ישר למאמרים

ואולי גם לשאלות הנפוצות, שיהיה, ככה בהזדמנות.
 

orennahum

New member
דוגמאות והסברים

מצורף קובץ PDF שמכיל דוגמאות והסברים. אורן
 

DadleFish

New member
יפה מאוד,

אם יש לך עוד כאלו זה יכול להיות נחמד אם תעלה אותם לטובת שאלות של מתחילים.
 

orennahum

New member
יש עוד

מדובר בפרק מספר שהתחלתי לכתוב מזמן מזמן, ולא ממש המשכתי. אני יכול לפרסם עוד, אבל עדיף שיהיו שאלות ספציפיות ככה אני אוכל להשלים את הפרקים בהתאם לנדרש.
 

DadleFish

New member
כרצונך ../images/Emo13.gif

הפרק נראה לא רע (למרות שהייתי משפר פה ושם), למה הפסקת?
 

orennahum

New member
בעיקר בגלל זמן

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

demultiplexer

New member
אשמח לקבל את החלק ל רישמות מקושרות

אשמח לקבל את החלק ל רישמות מקושרות
 
וואו! ../images/Emo13.gif

ריפרפתי ונראה נחמד מאד! חבל, אתה מפסיד ימבה כסף...
 

DadleFish

New member
זה לא בשבילי אישית,

אני את החומר הזה שכחתי כבר מזמן
אם יש לך מדריכים טובים אולי אפשר לשים אותם פה במאמרים או משהו כזה.
 

orennahum

New member
רשימות מקושרת

בשביל כל מי שביקש את הפרק על רשימות מקושרות. יש לי בעיה להעלות את הקובץ, כי הוא גדול מידי. האם למשהו יש פתרון לזה ? אורן
 

demultiplexer

New member
אין לך IIS מותקן ? או חבילת אכסון ?

העלה את זה לאיפה שאתה מאחסן את האתר שלך או לIIS שלך ושלח לנו לינק.
 

orennahum

New member
תשובה

יש לי אפצי מותק על המחשב, אבל אני לא מעוניין להפוך את המחשב שלי לנגיש לכל אחד באופן קבוע. אורן
 
למעלה