introduction to programming in c

26
1 1 Introduction to Programming in C ללללל8

Upload: baxter

Post on 05-Jan-2016

47 views

Category:

Documents


0 download

DESCRIPTION

Introduction to Programming in C. תרגול 8. 1. 1. רקורסיה תזכורת. הגדרה : המונח רקורסיה (recursion) מתאר מצב שבו פונקציה קוראת לעצמה באופן ישיר או באופן עקיף. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Introduction to  Programming in C

111

Introduction to Programming in C

8תרגול

Page 2: Introduction to  Programming in C

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

או באופן עקיף.

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

רקורסיהתזכורת

Page 3: Introduction to  Programming in C

abc – 1תרגיל מס'

כתוב פונקציה רקורסיבית אשר חתימתה היא:void abc(char arr[],int lastPlace, int curPlace)

-ים, את אינדקס סוף המערך ומספר שלם charהמקבלת מערך של שהוא המקום במערך ממנו אנו מעונינים להתחיל במילוי המערך

).0בתווים (בקריאה ראשונה יהיה מס' זה שווה ל-

הפונקציה מדפיסה את כל האפשרויות למלא את המערך מהמקום a,b,c באותיות lastPlace, עד המקום curPlaceשקיבלה,

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

Page 4: Introduction to  Programming in C

abc – 1תרגיל מס' למשל: עבור התוכנית הבאה:

void abcInvokingFun(char word[],int lengthOfWord){abc(word, lengthOfWord,0);

}

void main(){char word[5];abcInvokingFun(word,3);

}:נקבל את הפלטaaa aab aac aba abb abc aca acb acc baa

babbac bba bbb bbc bca bcb bcc caa cab cac

cbacbb cbc cca ccb ccc

Page 5: Introduction to  Programming in C

כתובתו של תחילת המערך

המקום הנוכחי

שאנחנו משנים

תנאי העצירה: 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);

}

abc – 1תרגיל מס'

Page 6: Introduction to  Programming in C

abc – 1תרגיל מס'

curPlace=2

curPlace=0

curPlace=3

curPlace=1

aabaac aba abb

abc acaacbacc baa bab

bac bba

bbb

bbc bcabcbbcc caacabcac cbacbbcbc ccaccb ccc

aaaaabaac abaabbabc acaacbacc baababbac bbabbbbbc bcabcbbcc caacabcac cbacbbcbc ccaccb ccc

הדפסה:

aa? ab? ac? ba? bb? bc? ca? cb? cc?

a?? b ?? c??

???

aaa

נראה את תרשים הקריאות המתקבל מהרצת הדוגמא שלמעלה )בדומה לתרשים הקריאות שראינו בכתה(:

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

Page 7: Introduction to  Programming in C

2תרגיל מס'

- מציין 1 ערכים שלמים (20כתבו תוכנית הקולטת עד •סוף קלט) למערך ומוצאת את הערך המקסימאלי.

לשם כך, ניתן לפרק את הבעיה לשתי בעיות קטנות •יותר

שקולטת את המערךרקורסיביתכתבו פונקציה 1)

שמחזירה את הערך רקורסיביתכתבו פונקציה 2)המקסימאלי

Page 8: Introduction to  Programming in C

2תרגיל מס' int GetArray(int arr[], int i){

int num;if (i > MAX_LEN – 1){

return 0;}scanf("%d", & num);if (num!= -1) {

arr[i] = num;return GetArray(arr, i + 1)

+1;}

else {return 0;

}}

int Max(int a[], int i,int length){int max;if (i == length -1) {

return a[i];}max = Max(a, i + 1);return (a[i] > max ? a[i] :

max);}

int main(){int max,a[MAX_LEN],length;length = GetArray(a, 0);max=Max(a,0, length );printf(“max=%d\n”max);return 0;

}

Page 9: Introduction to  Programming in C

3תרגיל מס'

, תו sכתוב פונקציה רקורסיבית אשר מקבלת מחרוזת •ch ומספר שלם ,n -הפונקציה תחפש את המופע ה .n י של-ch במחרוזת s.ותחזיר את האינדקס שלו

2, והשלם b, התו ”abbc“: בהינתן המחרוזת דוגמא מופיע בפעם ’b‘. התו 2) הפונקציה תחזיר n(עבור

במחרוזת.2 באינדקס sהשנייה במחרוזת

Page 10: Introduction to  Programming in C

3תרגיל מס' int FindNOccurence(char s[], char ch, int n, int index){

if (n == 0)return index -1;

if (s[index] == '\0')return -1;

if (s[index] == ch)return FindNOccurence (s, ch, n – 1, index + 1);

return FindNOccurence(s, ch, n, index + 1);{

Page 11: Introduction to  Programming in C

4תרגיל מס' :נתונה הפונקציה הרקורסיבית הבאה

#include <stdio.h>int secret( int n){ If( n<0 )

return 1 + secret ( -1 * n); if ( n<10 )

return 1; return 1 + secret( n/10 );}

?secret(12345) ו- secret(-4321)מה הערך של עבור פרמטר חיובי ועבור פרמטר secretמה מבצעת הפונקציה

שלילי?כתוב פונקציה זו מחדש בצורה לא רקורסיבית.

Page 12: Introduction to  Programming in C

4תרגיל מס' :פתרון

בשני המקרים.5 סעיף א': הפונקציה מחזירה את מס' התווים שמייצגים את סעיף ב':

הארגומנט.

כך למשל הפלט של התוכנית הבאה:void main(){

char s[80];printf("%d\n",secret(-43221));printf("%d\n",secret(12345));

יהיה:65

}

Page 13: Introduction to  Programming in C

4תרגיל מס' כתוב אותה פונקציה בצורה לא רקורסיבית.

:פתרון

int iterSecret( int n){int len=1;if( n<0 ) {

n=(-1) * n;len++;

}while( n>=10 ) {

n/=10;len++;

}return len;

}

Page 14: Introduction to  Programming in C

עיין בפונקציה הבאה: 5תרגיל מס'

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..0הערך המוחזר של הפונקציה תמיד 2..0הערך המוחזר של הפונקציה יכול להיות 3..1הערך המוחזר של הפונקציה תמיד 4..1הערך המוחזר של הפונקציה יכול להיות 5., אם הערכים לא גדולים מידי,הפונקציה מחזירה b ו- a חיובייםבקבלת שני ערכים 6.

.!a! x bאת הערך של אף לא אחת מהתשובות לעיל. 7.

Page 15: Introduction to  Programming in C

) b=0 וגםa=0 (למשל כאשר5 :פתרון) b=1 וגםa=2 (יש להדגים למשל עבור 6+

Page 16: Introduction to  Programming in C

7 6 5 1 17

arr

Subset Sum problem. S ומספר שלם arrנתונה סדרת ערכים שלמים )כמערך(

. Sצ"ל: האם קיימת תת-סדרה במערך כך שסכומה

למשל עבור:

6תרגיל מס'

S=14ו-

וסכומה 7,6,1התשובה היא כן כי קיימת תת-סדרה במערך שהיא: 14.

Page 17: Introduction to  Programming in C

:האלגוריתם אפשרויות: 2 במערך, יש iעבור כל איבר

ומנסים למצוא ,i : כן לוקחים את האיבר ה-אפשרות א'•SubsetSum בגודל S-arr[i]-1 במערך קטן יותר ב.

, ומנסים למצוא i : לא לוקחים את האיבר ה-אפשרות ב'•SubsetSum בגודל S-1 במערך קטן יותר ב .

תנאי העצירה שלנו יהיו: במערך SubsetSum אז נמצא S==0אם קיבלנו באיזשהו שלב •

.1ונחזיר , אז הבחירות שלקחנו עד עכשיו n==0 או S<0אחרת, אם קיבלנו •

אזי עברנו את הסכום המבוקש ואם S<0אינן מובילות לפתרון (אם 0==n אזי עדיין לא הגענו לסכום ואין לרשותנו אברים מתוכם נוכל

.0לבחור) ונחזיר

6תרגיל מס'

Page 18: Introduction to  Programming in C

int SubsetSum(int arr[], int idx, int n, int S){ if (S==0) return 1; //This is stopping condition #1. if (S<0 || n==0) return 0; //This is stopping condition #2. return SubsetSum(arr, idx+1, n-1, S-arr[idx]) ||

SubsetSum(arr, idx+1, n-1, S);}

טיפול באפשרות ב'

טיפול באפשרות א'

6תרגיל מס'

Page 19: Introduction to  Programming in C

7תרגיל מס'

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

.sשווה בדיוק ל-

Page 20: Introduction to  Programming in C

int SubsetSum(int arr[], int idx, int n, int S){ if (S==0) return 1; //This is stopping condition #1. if (S<0 || n==0) return 0; //This is stopping condition #2. return SubsetSum(arr, idx+1, n-1, S-arr[idx]) +

SubsetSum(arr, idx+1, n-1, S);}

7תרגיל מס'

Page 21: Introduction to  Programming in C

המכיל מספרים m*nנתון מערך דו-מימדי בגודל •במערך מסלול חוקי . 100טבעיים קטנים מ-

, (m-1,n-1) ומסתיים בתא (0,0)מתחיל בתא כאשר ההתקדמות תלויה בספרת האחדות

והעשרות של המס' שבתא הנוכחי. דרכים 2, אז ישנם 13 רשום המס' (2,3)אם בתא

להתקדם מתא זה:.(3,6)+ בעמודות. כלומר לתא 3+ בשורות ו 1) 1.(5,4)+ בעמודות. כלומר לתא 1+ בשורות ו 3) 2

, נתייחס 3אם בתא רשום מס' חד ספרתי, למשל .03אליו כאל

8תרגיל מס'

Page 22: Introduction to  Programming in C

לדוגמה: מסלול אפשרי הוא המסלול הצבוע •בירוק.

כתבו פונקציה רקורסיבית המחזירה את מס' •המסלולים החוקיים במערך (כמובן שאסור

להשתמש בלולאות).

)המשך( 8תרגיל מס'

Page 23: Introduction to  Programming in C

)פתרון( 8תרגיל מס'

Page 24: Introduction to  Programming in C

X שמדפיסה את האות void X(int lines) רקורסיביתכתבו פונקציה תמיד אי-זוגי). lines שורות (נניח ש-linesבאמצעות כוכביות ב-

ניתן להשתמש בלולאות.

יודפס: X(9)לדוגמא עבור * * * * * * * * * * * * * * *

* * . הכוכבית הראשונה חייבת להופיע בתחילת השורה הראשונה

.אין להגדיר פונקציה נוספת

9תרגיל מס'

Page 25: Introduction to  Programming in C

:פתרון, אחר כך לפתור את תת-הבעיה עבור Xהרעיון הוא להדפיס את השורה הראשונה של

X ללא השורה הראשונה והאחרונה ואז להדפיס את השורה האחרונה (שהיא זהה לראשונה).

ניתן להדגים את סדר הפעולות הכרונולוגי בכל קריאה רקורסיבית באמצעות התרשים הבא:

9פתרן תרגיל מס'

Page 26: Introduction to  Programming in C

void X(int lines){int static blank;int I;for (i=0; i<blank; i++)

putchar(' ');putchar('*');

if(lines==1){puts("");return;

} for (i=0; i<lines-2; i++)

putchar(' ');puts("*");

blank++;X(lines-2);blank--;for (i=0; i<blank; i++) putchar(' ');

putchar('*');for (i=0; i<lines-2; i++)

putchar(' ');puts("*");

}

9פתרון תרגיל מס'