פונקציות תכנות בשפת סי תרגול 7. הגדרה: המונח רקורסיה (recursion) מתאר מצב שבו פונקציה קוראת לעצמה באופן ישיר או באופן עקיף. שימוש: נוח להשתמש בפונקציות.

Slides:



Advertisements
Similar presentations
מבוא למדעי המחשב לתעשייה וניהול
Advertisements

מבוא למדעי המחשב לתעשייה וניהול דוגמאות ותרגול נוסף במערך חד ממדי הרצאה 12.
רקורסיות נושאי השיעור פתרון משוואות רקורסיביות שיטת ההצבה
חורף - תשס " ג DBMS, Design1 שימור תלויות אינטואיציה : כל תלות פונקציונלית שהתקיימה בסכמה המקורית מתקיימת גם בסכמה המפורקת. מטרה : כאשר מעדכנים.
תכנות תרגול 6 שבוע : חישוב e זוהי הנוסחא לחישוב e נראה כיצד לתרגם אותה לפונקציה n n.
תרגול 5 רקורסיות. רקורסיה קריאה של פונקציה לעצמה –באופן ישיר או באופן עקיף היתרון : תכנות של דברים מסובכים נעשה ברור ונוח יותר, מכיוון שזו למעשה צורת.
מה החומר למבחן ? כל החומר שנלמד בהרצאות ובתרגולים. לגבי backtracking: לא תידרשו לממש אלגוריתם, אך כן להבין או להשלים מימוש נתון. אחת משאלות המבחן מבוססת.
תכנות תרגול 4 שבוע : לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
רקורסיות נושאי השיעור מהן רקורסיות פתרון רקורסיות : שיטת ההצבה שיטת איטרציות שיטת המסטר 14 יוני יוני יוני 1514 יוני יוני יוני 1514.
תכנות תרגול 2 שבוע : שבוע שעבר כתבו תוכנית המגדירה שלושה משתנים מאתחלת אותם ל 1 2 ו 3 ומדפיסה את המכפלה שלהם את ההפרש שלהם ואת הסכום שלהם.
מבוא לשפת C חידות ונקודות חשובות נכתב על-ידי יורי פקלני. © כל הזכויות שמורות לטכניון – מכון טכנולוגי לישראל.
11 Introduction to Programming in C תרגול
מבוא למדעי המחשב תרגול 8 - מחרוזות שעת קבלה : יום שני 11:00-12:00 דוא " ל :
חורף - תשס " ג DBMS, צורות נורמליות 1 צורה נורמלית שלישית - 3NF הגדרה : תהי R סכמה רלציונית ותהי F קבוצת תלויות פונקציונליות מעל R. R היא ב -3NF.
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
מבוא למדעי המחשב תרגול 4 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
מבוא למדעי המחשב © אריק פרידמן 1 מצביעים כמערכים דוגמה.
1 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
תכנות תרגול 6 שבוע : תרגיל שורש של מספר מחושב לפי הסדרה הבאה : root 0 = 1 root n = root n-1 + a / root n-1 2 כאשר האיבר ה n של הסדרה הוא קירוב.
מבוא לשפת C תרגול 12: עוד רקורסיה
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
1 Formal Specifications for Complex Systems (236368) Tutorial #1 Course site : T.A. :Emilia Katz.
ערמות ; מבני נתונים 09 מבוסס על מצגות של ליאור שפירא, חיים קפלן, דני פלדמן וחברים.
תכנות תרגול 6 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
Backpatching 1. תזכורת מתרגול קודם קוד ביניים - שפת הרביעיות שיטות לייצור קוד ביניים –שימוש בתכונת code –כתיבה ישירה ל-buffer של פקודות שיטות לתרגום מבני.
מבוא כללי למדעי המחשב שיעור 5
תכנות תרגול 10 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
מבוא כללי למדעי המחשב תרגול 3. לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
תכנות בשפת C תרגול 9 רקורסיה המשך
ערכים עצמיים בשיטות נומריות. משוואה אופינית X מציין וקטור עצמי מציינת ערך עצמי תואם לוקטור.
מבוא כללי למדעי המחשב תרגול 5. חישוב e זוהי הנוסחא לחישוב e נראה כיצד לתרגם אותה לפונקציה n n.
מבוא למדעי המחשב תרגול 6 - מערכים שעת קבלה : יום שני 11:00-12:00 דוא " ל :
Data Structures, CS, TAU, Perfect Hashing 1 Perfect Hashing בעיה : נתונה קבוצה S של n מפתחות מתחום U השוואה ל - Hash : * טבלה קבועה (Hash רגיל - דינאמי.
תכנות תרגול 5 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
1 Data Structures, CS, TAU, Perfect Hashing בעיה: נתונה קבוצה S של n מפתחות מתחום U השוואה ל- Hash : * טבלה קבועה (Hash רגיל - דינאמי) * רוצים זמן קבוע.
מערכים עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר int grade1, grade2, …, grade20; int grade1, grade2, …, grade20;
עקרון ההכלה וההדחה.
תכנות תרגול 4 שבוע : לולאות for לולאות for for (counter=1 ;counter
מבוא למדעי המחשב תרגול 3 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
Markov Decision Processes (MDP) תומר באום Based on ch. 14 in “Probabilistic Robotics” By Thrun et al. ב"הב"ה.
תכנות בשפת C תרגול 15 תרגול חזרה 2 תרגילים ממבחנים
מתמטיקה בדידה תרגול 2.
1 מבוא למדעי המחשב סיבוכיות. 2 סיבוכיות - מוטיבציה סידרת פיבונאצ'י: long fibonacci (int n) { if (n == 1 || n == 2) return 1; else return (fibonacci(n-1)
1 מבוא למדעי המחשב backtracking. 2 מוטיבציה בעיית n המלכות: נתון: לוח שחמט בגודל. המטרה: לסדר על הלוח n מלכות כך שאף אחת לא תאיים על השנייה. דוגמא: עבור.
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
Sscanf example #include int main () { char sentence []="Rudolph is 12 years old"; char str [20]; int i; sscanf (sentence,"%s %*s %d",str,&i); printf ("%s.
תכנות תרגול 8 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
1 מבוא למדעי המחשב רקורסיה. 2 רקורסיה היא שיטה לפתרון בעיות המבוססת על העיקרון העומד ביסוד אינדוקציה מתמטית: אם ידועה הדרך לפתור בעיה עבור המקרים הבסיסיים.
הגדרת משתנים יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר.
מבוא למדעי המחשב לתעשייה וניהול הרצאה 7. סברוטינות subroutines.
תכנות מכוון עצמים ושפת ++C וויסאם חלילי. TODAY TOPICS: 1. Function Overloading & Default Parameters 2. Arguments By Reference 3. Multiple #include’s 4.
1 Formal Specifications for Complex Systems (236368) Tutorial #1 Course site:
מספרים אקראיים ניתן לייצר מספרים אקראיים ע"י הפונקציה int rand(void);
Programming Arrays.
Formal Specifications for Complex Systems (236368) Tutorial #1
מבוא למדעי המחשב סיבוכיות.
רקורסיות קרן כליף.
Introduction to Programming in C
רקורסיות קרן כליף.
Computer Programming Summer 2017
מבוא כללי למדעי המחשב תרגול 4
תרגול 8 תחומי הכרה פונקציות
שאלות מבחינות קודמות יואב ציבין.
Introduction to Programming in C
Introduction to Programming in C
תרגול Introduction to C - Fall Amir Menczel.
NG Interpolation: Divided Differences
Computer Programming תרגול 3 Summer 2016
Engineering Programming A
מבוא לתכנות ב- Java תרגול 10 - רשימות מקושרות.
Presentation transcript:

פונקציות תכנות בשפת סי תרגול 7

הגדרה: המונח רקורסיה (recursion) מתאר מצב שבו פונקציה קוראת לעצמה באופן ישיר או באופן עקיף. שימוש: נוח להשתמש בפונקציות רקורסיביות ע"מ לפתור בעיות בעלות אופי רקורסיבי. באופן כללי, השיטה תהיה להקטין את מימד הבעיה, לפתור את הבעיה על המימד היותר קטן ולהשתמש בפיתרון שמתקבל ע"מ לפתור את הבעיה במימד אחד יותר גבוהה. רקורסיה

דוגמה מס ' 1- חישוב עצרת : א) חישוב n! באופן איטרטיבי: int iterFactorial(int n) { int res=1; while(n>0) { res*=n; n--; } return res; } ב) חישוב n! באופן רקורסיבי: int recFactorial(int n) { if(n<=1) return 1; return n*recFactorial(n-1); }

דוגמה מס ' 1- חישוב עצרת : בעת שימוש בפונקציה זו לחישוב 3!, תרשים הסביבות יראה כך : recFactorial(3) n=3 if(n<=1) return 1; return 3* recFactorial(2) void main() { n=2 if(n<=1) return 1; return 2* recFactorial(1) n=1 if(n<=1) return 1;

תזכורת – משתנים סטאטיים מגדירים באופן הבא: static int var; ניתן לאתחל בשורת ההגדרה בלבד כאשר חייבים לאתחל בביטויי קבוע!!! אם אנחנו לא מאתחלים אותם, המערכת תאתחל אותם אוטומטית לאפס. הscope- של משתנים סטאטיים הוא רק הפונקציה שבה הם הוגדרו אך הם ממשיכים להתקיים גם אחרי שביצוע הפונקציה נגמר (למעשה עד סוף ריצת התוכנית). לפיכך הערך של משתנה סטאטי בפונקציה כלשהי נשמר בין קריאות עוקבות לפונקציה זו.

דוגמה מס ' 2 – harmonic number מס ' הרמוני של המס ' השלם n מוגדר באופן הבא : ברצוננו לכתוב פונקציה רקורסיבית rec_harmonic_num(n) אשר תדפיס למסך את הפיתוח של h(n). למשל, עבור הקריאה rec_harmonic_num(5), נקבל על המסך : 1/5+1/4+1/3+1/2+1=2.28

דוגמה מס ' 2 – harmonic number void rec_harmonic_sum(int n) { static double sum=1; if(n==1)/*Stop condition*/ { printf("1=%.2f\n",sum); sum=1; /*Must initialize the static variable "sum" so that we can call this function repeatedly in the same program run. Make sure you understand why!!! */ return; } printf("1/%d+",n); sum+=1./n; /*The "1." syntax is used in order to prevent automatic casting to integer type (so that the expression "1/n" will be evaluated as type double). */ rec_harmonic_sum(n-1); /*The recursive call. */ }

דוגמה מס ' 3 – abc כתוב פונקציה רקורסיבית בשם void abc(char arr[],int lastPlace, int curPlace), המקבלת מערך של char-ים, את אינדקס סוף המערך ומספר שלם שהוא המקום במערך ממנו אנו מעונינים להתחיל במילוי המערך בתווים (בקריאה ראשונה יהיה מס' זה שווה ל- 0). הפונקציה מדפיסה את כל האפשרויות למלא את המערך מהמקום שקיבלה, curPlace, עד המקום lastPlace באותיות a,b,c במילים אחרות, מטרת הפונקציה היא להדפיס את כל האפשרויות ליצור מילה באורך מסוים בעזרת האותיות a,b,c.

דוגמה מס ' 3 – abc למשל: עבור התוכנית הבאה: void abcInvokingFun(char word[],int lengthOfWord) { abc(word, lengthOfWord,0); } void main() { char word[5]; abcInvokingFun(word,3); } נקבל את הפלט: aaaaabaacabaabbabcacaacbaccbaa bab bacbbabbbbbcbcabcbbcccaacabcac cba cbbcbcccaccbccc

כתובתו של תחילת המערך המקום הנוכחי שאנחנו משנים תנאי העצירה : אם הגענו ל - lastPlace אז שים במקום הנוכחי יש '0\' ( הגענו לסוף ), הדפס את המחרוזת ( מהתחלתה ) וחזור. כעת אנחנו עובדים על המקום curPlace במערך :  הצב בו a, וקרא לפונק ' abc ( עם כתובת המערך, ואינדקס המקום הבא ) אשר תדאג למילוי כל האפשרויות הקימות בשאר המערך.  לאחר שחזרת, הצב את b במקום a, ושוב קרא לפונק ' עם המקום הבא במערך כפרמטר.  כנ " ל לגבי c. אינדקס סוף המערך void abc(char arr[],int lastPlace, int curPlace) { if (curPlace == lastPlace) { arr[curPlace]='\0'; printf("%s\t",arr); return; } arr[curPlace] = 'a'; abc (arr,lastPlace,curPlace+1); arr[curPlace] = 'b'; abc (arr,lastPlace,curPlace+1); arr[curPlace] = 'c'; abc (arr,lastPlace,curPlace+1); } דוגמה מס ' 3 – abc

curPlace=2 curPlace=0 curPlace=3 curPlace=1 נראה את תרשים הקריאות המתקבל מהרצת הדוגמא שלמעלה ( בדומה לתרשים הקריאות שראינו בכתה ): כל ריבוע מייצג קריאה לפונקציה, כאשר בתוך כל ריבוע מופיע תוכן המערך שהפונקציה מקבלת. ערך הפרמטר curPlace הוא משותף לכל רמה בתרשים ומצויין בצד ימין.

תרגיל מס ' 1 נתונה הפונקציה הרקוסיבית הבאה: #include int secret( int n) { if( n<0 ) return 1 + secret ( -1 * n); if ( n<10 ) return 1; return 1 + secret( n/10 ); } מה הערך של secret(-4321) ו- secret(12345) ? פתרון: 5 בשני המקרים.

תרגיל מס ' 1 הסבר בקצרה מה מבצעת הפונקציה secret עבור פרמטר חיובי ועבור פרמטר שלילי. פתרון : הפונקציה מחזירה את מס ' התווים שמייצגים את הארגומנט. כך למשל הפלט של התוכנית הבאה : void main() { char s[80]; printf("%d\n",secret(-43221)); printf("%d\n",secret(12345)); יהיה :6 5 }

תרגיל מס ' 1 כתוב אותה פונקציה בצורה לא רקורסיבית. פתרון: int iterSecret( int n) { int len=1; if( n<0 ) { n=(-1) * n; len++; } while( n>=10 ) { n/=10; len++; } return len; }

תרגיל מס ' 2 עיין בפונקציה הבאה: int what(int a, int b) { if(!a && !b) return 1; if(a > b)return a * what(a-1, b); return b * what(a, b-1); } בהנחה שהפונקציה הנ"ל מקבלת שני ערכים אי-שליליים (חיוביים או אפס), סמן את כל התשובות הנכונות (בדף התשובות): 1.הפונקציה נכנסת לרקורסיה אינסופית. 2.הערך המוחזר של הפונקציה תמיד 0. 3.הערך המוחזר של הפונקציה יכול להיות 0. 4.הערך המוחזר של הפונקציה תמיד 1. 5.הערך המוחזר של הפונקציה יכול להיות 1. 6.בקבלת שני ערכים חיוביים a ו- b, אם הערכים לא גדולים מידי,הפונקציה מחזירה את הערך של a! x b!. 7. אף לא אחת מהתשובות לעיל. פתרון: 5 (למשל כאשר a=0 וגם b=0) + 6 (יש להדגים למשל עבור a=2 וגם b=1 )

תרגיל מס ' 3Subset Sum Problem arr נתונה סדרת ערכים שלמים (כמערך arr ומספר שלם S ) צ " ל : האם קיימת תת - סדרה במערך כך שסכומה S למשל : ו - S=14. התשובה היא כן כי קיימת תת - סדרה במערך שהיא : 7,6,1 וסכומה 14. האלגוריתם : יש לנו כאן 2 אפשרויות עבור כל איבר i במערך :  אפשרות א ': לוקחים את האיבר ה - i ומנסים למצוא SubsetSum בגודל S-arr[ i ] במערך קטן יותר ב -1.  אפשרות ב ': לא לוקחים את האיבר ה - i ומנסים למצוא SubsetSum בגודל S במערך קטן יותר ב -1. תנאי העצירה שלנו יהיו : 1) אם קיבלנו באיזשהו שלב S==0 אזי יש לנו SubsetSum במערך ונחזיר 1. 2) אחרת אם קיבלנו S<0 או 0==n אזי הבחירות שלקחנו עד עכשיו אינן מובילות לפתרון ( אם S<0 אזי עברנו את הסכום המבוקש ואם 0==n אזי עדיין לא הגענו לסכום ואין לרשותנו אברים מתוכם נוכל לבחור ) ונחזיר 0.

תרגיל מס ' 3 טיפול באפשרות בטיפול באפשרות א ' int SubsetSum(int arr[], int n, int S) { if (0==S) return 1; //This is stopping condition #1. if (S<0 || 0==n) return 0; //This is stopping condition #2. return SubsetSum(arr+1,n-1,S) || SubsetSum(arr+1,n-1,S-arr[0]); } איך ניתן למצא את תת-הסדרה שסכום איבריה הינו S, בהנחה שזו אכן קיימת? נעבור פעם אחת על המערך ונשאל עבור כל איבר i במערך האם יש SubsetSum בגודל S במערך [[i+1,...,n. אם יש אזי לא ניקח את האיבר ה-i ונמשיך לאיבר הבא עם S. אם אין אזי האבר ה-i בטוח ב-SubsetSum,לכן ניקח אותו ונמשיך לאיבר הבא עם S=S-arr[i].

תת - הסידרה שאגרנו עד כה !!! האינדקס של subseq שגם מציין את מס ' האיברים שיש בה ברגע ההדפסה !!! להלן תכנית המדפיסה את כל תתי - הסדרות האפשריות : #include void printArr(int arr[], int n) { int i ; puts(""); for (i=0; i<n; i++) printf (" %d",arr[i]); puts(""); } int SubsetSum(int arr[], int n, int S, int subseq[],int count) { int withCurrent, withoutCurrent; if (S==0) { printArr(subseq,count); return 1; } if (S< 0 || !n) return 0; subseq[count] = arr[0]; withCurrent = SubsetSum(arr+1,n-1,S-arr[0],subseq, count+1); withoutCurrent= SubsetSum(arr+1,n-1,S,subseq,count); return (withoutCurrent || withCurrent); } void main() { int arr[] = {7, 6, 5,1,7,13,17}, subseq[8]; int S = 14,arrSize = 7; if (!SubsetSum(arr,arrSize,S,subseq,0)) printf("\nThere is no subsequence\n"); }

תרגיל מס ' 4 רקורסיה עם backtracking backtracking – דרך רקורסיבית לפתרון בעיות באמצעות בדיקה שיטתית של כל הפתרונות האפשריים. את הפתרונות הלא נכונים אנו פוסלים ולא מנסים יותר מפעם אחת. בסוף אנו נותרים עם הפתרון הנכון. נסתכל על הדוגמה הבאה : הציור מייצג מבוך. נניח והיינו רוצים להגיע מחדר A לחדר B. כדי להבין את שיטת ה -Backtrack נתאר דרך לפתרון הבעיה ( בכל חדר אנו רואים רק את החדרים אליהם ניתן להגיע ואין אנו רואים את המבוך כולו ). 1. עבור מחדר A לחדר בחדר 2 ישנם שתי אפשרויות. נבחר לעבור לחדר הגענו למבוי סתום, נחזור לחדר 2. ובחדר 2 נבחר הפעם לעבור לחדר נעבור לחדר 4. ( כי אין ברירה אחרת ). 5. בחדר 4 ישנם שתי אפשרויות. נבחר למשל, לעבור לחדר שוב פעם שתי אפשריות נבחר בחדר הגענו למבוי סתום. נחזור לחדר 6 ושם נבחר לעבור לחדר הגענו למבוי סתום. נחזור לחדר 6 ונבין שמימשנו את כל האפשרויות להתקדם דרך חדר 6 לכן נחזור לחדר נתקדם לחדר נתקדם ל -B. וסיימנו את המבוך. ניתן למשל לייצג מבוך ב -C ע " י מערך שלמים דו - מימדי. התא ה -( i, j ) של המטריצה מייצג קיום ( ערך 1) או אי קיום ( ערך 0) מעבר בין חדר i וחדר j.

תרגיל מס ' 4 #include #define N 10 #define no_pass 0 #define yes_pass 1 #define not_visited 0 /*This function tells us wether we can move from i to j*/ int canGo (int maze[N][N],int i,int j) { return maze[i][j]; }

תרגיל מס ' 4 int find_way(int maze[N][N],int curRoom) { static int visit[N]={not_visited}; int nextRoom; if (visit[curRoom]) /*So that we don't walk around in circles! */ return 0; visit[curRoom]=1; /*Mark that we have already visited this chamber. */ if (curRoom==0) /*If we found a way from the begining point, A. */ { printf("There is a path and it is:\n A=>"); return 1; } /*Run over all rooms smaller than the last one, and if there is a passage from the current room to them, find a way from them to the destination point B. If there is a way from them, add the current room to the path and return 1. */ for(nextRoom = N-2; nextRoom >= 0; nextRoom--) { /*Check if there is a passage from the current room to the next one: */ if (canGo(maze,curRoom,nextRoom)) /*Check if there is way to get from the next room to B, if so return 1: */ if (find_way(maze,nextRoom)) { printf("%d=>",curRoom); return 1; } return 0; /*If there is no way from the current room to B. */ }

תרגיל מס ' 4 void main() { int maze[N][N] = {no_pass}; maze[0][2] = yes_pass; maze[1][2] = yes_pass; maze[2][0] = yes_pass; maze[2][1] = yes_pass; maze[2][3] = yes_pass; maze[3][2] = yes_pass; maze[3][4] = yes_pass; maze[4][3] = yes_pass; maze[4][5] = yes_pass; maze[4][6] = yes_pass; maze[5][4] = yes_pass; maze[5][9] = yes_pass; maze[6][4] = yes_pass; maze[6][7] = yes_pass; maze[6][8] = yes_pass; maze[7][6] = yes_pass; maze[8][6] = yes_pass; maze[9][5] = yes_pass; if (find_way(maze,N-1)) printf("B.\n"); else printf("There is no path\n"); }