אוניברסיטת חיפה החוג למדעי המחשב מבוא למדעי המחשב סמסטר ב' תשע"ב בחינת סיום, מועד ב',.02..9.7 מרצה: אורן וימן מתרגלים: נעמה טוויטו ועדו ניסנבוים מדריכי מעבדה: מחמוד שריף ומיקה עמית משך המבחן: שעתיים חומר עזר: אסור הנחיות: 1. עליכם לכתוב את התשובות על הטופס ולהגיש את כל הטופס ואת הטופס בלבד. 2. היציאה מהכיתה במהלך הבחינה אסורה. 3. קראו היטב כל שאלה וודאו שאתם מבינים אותה לפני שתתחילו לענות עליה. אם יש שאלות, פנו למרצה או למתרגלים. 4. כתבו בכתב יד ברור וקריא. ניתן לכתוב בעיפרון. 5. ניתן לכתוב הערות בעברית, גם בגוף פונקציות C. בהצלחה!!! שאלה 2. 3 4 סה"כ ציון /10 /30 /25 /35 /111
שאלה )20 2 נק'( א. נתונים המערכים/משתנים הבאים בזיכרון המחשב: int a[] = {6,5,4,3,2,1; char *b[] = {"Moed", "Bet", "is", "even", "more", "fun", "than", "Aleph"; char* d[] = {*(b+a[2]), *(b+a[1]); int e[3][3] = { {0,3,4, {1,2,7, {2,4,7 ; int f[] = { b[3][3] - b[4][0], a[2]+a[4], e[1][2] - e[0][1]; כתבו מה יודפס ע"י הפקודות הבאות: printf("%d", e[1][1] - a[e[1][1]] ); printf("%d", f[1] + *(f+2) ); printf("%c", *(*(d+1)+2)); printf("%d", (**(b+1) - 'A')); printf("%d", *((int *)e+4) ); -2 10 n 1 2
שאלה. )30 נק'( בשאלה זו, המערך a מכיל מספרים שלמים, כך שכל מספר מופיע פעם אחת לכל היותר: void func1(int a[], int x) int i = 0; while(x>0) if( x%2 == 1 ) printf(" %d ",a[i]); x /=2; i++; int func2(int n, int x) int temp; if(x == 0) return 1; temp = func2(n,x/2); if( x%2 ) return n*temp*temp; return temp*temp; void func3(int a[], int n) int x = 0,y; y = func2(2,n); while( x<y ) printf("{"); func1(a, x); printf("\n"); x++; 1. הסבירו בשורה או שתיים מה עושה כל אחת מהפונקציות: יש 1 במיקום ה- i x כך שבייצוג הבינארי של a[i] מדפיסה את כל האיברים :func1 x n מחשבת את :func2 מדפיסה את כל תתי הקבוצות של איברים ב- a. :func3
2. מה סיבוכיות הזמן של כל אחת מהפונקציות: O(logx) :func1 O(logx) :func2 O(n2 n ) :func3 3. כתבו פונקציה func4 שהיא לא רקורסיבית וחתימתה (x int func4 (int,n int אשר הקריאה אליה תגרום לתוצאה זהה לזו המתקבלת מקריאה ל- func2. int func4(int n, int x) int i,res = 1; for(i=0 ; i<x ; i++) res *= n; return res; {
שאלה )25 3 נק'( בהינתן מערך ממוין, הסטה מעגלית שלו תוגדר כהזזת כל איבר במערך תא אחד ימינה, כאשר האיבר האחרון במערך מועבר לתא הראשון. לדוגמא: מערך ממוין שהופעלו עליו מספר שלם כלשהו של הסטות מעגליות )1 הסטות או יותר( ייקרא מערך ממוין בהסטה. לדוגמה, המערכים הבאים ממוינים בהסטה: )הופעלו 2 הסטות( )הופעלו 4 הסטות( )הופעלו 1 הסטות( 1. עליכם לממש פונקציה רקורסיבית שחתימתה )n iscirc)int,[]a int המקבלת מערך a באורך n. הפונקציה מחזירה 1 אם המערך ממוין בהסטה )שימו לב שגודל ההסטה אינו ידוע( ו- 1 אחרת. על הפונקציה לעבוד בזמן.O(n) שימו לב: בסעיף זה אסור בכלל להשתמש בלולאות! כלומר, אסור להשתמש ב- while.for,while,do כמו כן, אסור להשתמש בפונקציות עזר נוספות. יש לכתוב פונקציה אחת בלבד עם החתימה הנתונה. עם זאת, מותר להשתמש במשתנים חיצוניים. int flag=0; int firstval; int iscirc(int a[], int n) { if(!flag){ flag++; firstval=*a; if(n==1){ if(*a > firstval) flag++; return (flag<3); if(*a > *(a+1)) flag++; if(flag==3) return 0; return iscirc(a+1,n-1);
2. בסעיף זה, עליכם לממש את הפונקציה )x findcirc)int,[]a int,n int שמקבלת מערך a שהוא ממוין בהסטה )שימו לב שגודל ההסטה אינו ידוע( את גודלו n וערך x, ומחפשת בו את הערך x. הפונקציה מחזירה את האינדקס במערך a שבו x נמצא, או )1-( אם x אינו נמצא במערך. בסעיף זה ניתן להניח כי כל אברי המערך שונים זה מזה. שימו לב: בסעיף זה מותר לכתוב עוד פונקציות עזר ומותר להשתמש בלולאות. שימו לב כי קיים פתרון בסיבוכיות זמן,O(logn( פתרון בסיבוכיות זמן גבוהה מזו לא יזכה בנקודות. int findcirc(int a[], int n, int x) { int low=0, high=n-1, mid; while (high >= low) { mid = (low+high)/2; if (a[mid] == x) return mid; if (a[high] > a[low]) { if (a[mid]>x) high=mid-1; else low=mid+1; else if (a[mid] > a[high]) { if (x>=a[low] && x<=a[mid]) high=mid-1; else low=mid+1; else { if (x>=a[mid] && x<=a[high]) low=mid+1; else high=mid-1; return -1;
שאלה )33 4 נק'( נתונה ההגדרה הבאה של צמתים בעץ בינארי: typedef struct node { int data; /* the number in the node */ struct node *left, *right; /* left and right children */ Node; עץ בינארי יקרה עץ שיקוף עם לכל מסלול בעץ, אם נחליף את בחירת הבן בכל הסתעפות יתקיים א. ב. המסלול יהיה תקין כלומר יגיע לצומת בעץ. הערך שבצומת הזה יהיה זהה לערך שבצומת אליו הגענו במסלול המקורי. כך למשל בעץ הבא: 1 2 2 4 5 המסלול >L,L< )כלומר Left ואז שוב )Left יוביל ל- 4 ואילו המסלול ההופכי >R,R< )כלומר Right ואז שוב )Right יוביל ל- 5 ולכן זהו אינו עץ שיקוף. העץ הבא לעומת זאת הוא כן עץ שיקוף: 1 2 2 4 3 3 4 זאת מפני שכל המסלולים ישמרו עם היפוך הבחירות: 1. המסלול >L,L< יוביל ל- 4 וגם המסלול ההופכי >R,R< יוביל ל- 4
2. המסלול >L,R< יוביל ל- 3 וגם המסלול ההופכי >R,L< יוביל ל- 3 3. המסלול >L< יוביל ל- 2 וגם המסלול ההופכי >R< יוביל ל- 2 1 בעץ הבא: 2 2 4 למסלול >L,L< בכלל לא קיים מסלול שיקוף >R,R< ולכן העץ אינו עץ שיקוף. עליכם לכתוב פונקציה שחתימתה ;(p int IsMirror(Node* הפונקציה מקבלת שורש של עץ ומחזירה 1 אם העץ הוא עץ שיקוף ו- 1 אחרת. הבהרות: 1. ניתן להוסיף שדות ל- node struct המוגדר לעיל. 2. ניתן להוסיף פונקציות עזר. 3. בעץ בינארי לכל צומת לכל היותר שני בנים )אך אולי פחות(. בן שאינו קיים מסומן ע"י,NULL כך שלמשל לעלה בעץ יש שני בנים ושניהם.NULL 4. לא ניתן להשתמש במשתנים חיצוניים או סטטיים. int IsMirror(Node* p) { if(p==null) return 1; return IsMirrorTwo(p->left, p->right); int IsMirrorTwo(Node* p, Node* q) { if(p==null && q==null) return 1; if((p==null && q!=null) (p!=null && q==null) (p->data!= q->data)) return 0; return (IsMirrorTwo(p->left, q->right) && IsMirrorTwo(p->right, q->left));