Download presentation
Presentation is loading. Please wait.
1
תכנות בשפת C תרגול 9 רקורסיה המשך...
2
תזכורת: רקורסיה הגדרה: המונח רקורסיה (recursion) מתאר מצב שבו פונקציה קוראת לעצמה באופן ישיר או באופן עקיף. שימוש: נוח להשתמש בפונקציות רקורסיביות ע"מ לפתור בעיות בעלות אופי רקורסיבי. באופן כללי, השיטה תהיה להקטין את מימד הבעיה, לפתור את הבעיה על המימד היותר קטן ולהשתמש בפיתרון שמתקבל ע"מ לפתור את הבעיה במימד אחד יותר גבוהה.
3
דוגמה מס' 1- חישוב עצרת: 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); }
4
דוגמה מס' 1- חישוב עצרת: בעת שימוש בפונקציה זו לחישוב 3!, תרשים הסביבות יראה כך: void main() { recFactorial(3) n=3 if(n<=1) return 1; return 3* recFactorial(2) n=2 if(n<=1) return 1; return 2* recFactorial(1) 6 n=1 if(n<=1) return 1; 2 1
5
דוגמא: מצביעים ורקורסיה
char * rec_strstr(char *st1, char *st2) { if(!(*st1)) return NULL; if(*st1==*st2 && doesTheRestMatch(st1+1,st2+1)) return st1; else return rec_strstr(st1+1,st2); } int doesTheRestMatch(char *st1, char *st2) { if(!(*st2)) return 1; if(*st1==*st2) return doesTheRestMatch(st1+1,st2+1); Else return 0; }
6
המשך דוגמא: מצביעים ורקורסיה
void main() { char st1[]="bnbnbacdhghg",st2[]="acd"; char *c; if(c= strstr(st1,st2)) printf ("The first character in both st2 and st1 is %c\n ",*c); else printf ("Sorry, st2 isn't contained in st1!!!\n"); } Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel
7
תרגיל מס' 1Subset Sum Problem
נתונה סדרת ערכים שלמים (כמערך arr ומספר שלם S ) צ"ל: האם קיימת תת-סדרה במערך כך שסכומה S. arr 17 1 5 6 7 למשל: ו- S=14. התשובה היא כן כי קיימת תת-סדרה במערך שהיא: 7,6,1 וסכומה 14. האלגוריתם: יש לנו כאן 2 אפשרויות עבור כל איבר i במערך: אפשרות א': לוקחים את האיבר ה- i ומנסים למצוא SubsetSum בגודל S-arr[i] במערך קטן יותר ב-1. אפשרות ב': לא לוקחים את האיבר ה- i ומנסים למצוא SubsetSum בגודל S במערך קטן יותר ב-1. תנאי העצירה שלנו יהיו: אם קיבלנו באיזשהו שלב S==0 אזי יש לנו SubsetSum במערך ונחזיר 1. אחרת אם קיבלנו S<0 או 0==n אזי הבחירות שלקחנו עד עכשיו אינן מובילות לפתרון (אם S<0 אזי עברנו את הסכום המבוקש ואם 0==n אזי עדיין לא הגענו לסכום ואין לרשותנו אברים מתוכם נוכל לבחור) ונחזיר 0.
8
תרגיל מס' 1 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].
9
להלן תכנית המדפיסה את כל תתי-הסדרות האפשריות: #include <stdio.h>
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"); } להלן תכנית המדפיסה את כל תתי-הסדרות האפשריות: #include <stdio.h> 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); האינדקס של subseq שגם מציין את מס' האיברים שיש בה ברגע ההדפסה!!!
10
תרגיל מס' 2 רקורסיה עם backtracking
בסוף אנו נותרים עם הפתרון הנכון.נסתכל על הדוגמה הבאה: הציור מייצג מבוך. נניח והיינו רוצים להגיע מחדר A לחדר B. כדי להבין את שיטת ה-Backtrack נתאר דרך לפתרון הבעיה (בכל חדר אנו רואים רק את החדרים אליהם ניתן להגיע ואין אנו רואים את המבוך כולו). עבור מחדר A לחדר 2. בחדר 2 ישנם שתי אפשרויות. נבחר לעבור לחדר 1. הגענו למבוי סתום, נחזור לחדר 2. ובחדר 2 נבחר הפעם לעבור לחדר 3. נעבור לחדר 4. (כי אין ברירה אחרת). בחדר 4 ישנם שתי אפשרויות. נבחר למשל, לעבור לחדר 6. שוב פעם שתי אפשריות נבחר בחדר 8. הגענו למבוי סתום. נחזור לחדר 6 ושם נבחר לעבור לחדר 7. הגענו למבוי סתום. נחזור לחדר 6 ונבין שמימשנו את כל האפשרויות להתקדם דרך חדר 6 לכן נחזור לחדר 4. נתקדם לחדר 5. נתקדם ל-B. וסיימנו את המבוך. ניתן למשל לייצג מבוך ב-C ע"י מערך שלמים דו-מימדי. התא ה-(i,j) של המטריצה מייצג קיום (ערך 1) או אי קיום (ערך 0) מעבר בין חדר i וחדר j.
11
תרגיל מס' 2 #include <stdio.h> #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]; }
12
תרגיל מס' 2 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 0; /*If there is no way from the current room to B. */
13
תרגיל מס' 2 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"); }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.