1 / 47

תכנות – שיעור 7

תכנות – שיעור 7. חזרה -מערכים. נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים זהים Type name[SIZE]; Char a[10]; int b[50]; הגודל חייב להיות קבוע. פנייה לאיברי המערך מתבצעת ע"י a[k] כאשר K בין 0 ל- SIZE-1 אתחול ע"י לולאה או רשימת אתחול. החלפה בין משתנים.

Download Presentation

תכנות – שיעור 7

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. תכנות – שיעור 7

  2. חזרה -מערכים • נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים זהים • Type name[SIZE]; • Char a[10]; int b[50]; • הגודל חייב להיות קבוע. • פנייה לאיברי המערך מתבצעת ע"י a[k] כאשר K בין 0 ל-SIZE-1 • אתחול ע"י לולאה או רשימת אתחול

  3. החלפה בין משתנים • נסתכל על התוכנית הבאה: int main() { int a,b,x,y,temp;  temp = x; x = y; y = temp;  temp = a; a = b; b = temp; } החלפת הערכים החלפת הערכים

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

  5. החלפה בין משתנים • נכתוב פונקציה כזו בשם swap void swap(int p, int q) { int tmp = p; p = q; q = tmp; }

  6. החלפה בין משתנים int main() { int a=10,b=2,x=3,y=5,temp;  swap(x,y);  swap(a,b); }

  7. החלפה בין משתנים • נעקוב אחרי הקריאה לפונקציה swap(x,y); void swap (int q,int p) { int temp = p; p = q; q = temp; }

  8. מצביעים • ראינו שכל משתנה שהגדרנו בתוכנית שלנו מוצקה עבורו תא באזור כלשהו בזיכרון. int main() { Int x,y; } • לכל תא כזה יש כתובת בזיכרון של המחשב. • כדי להגיע לכתובת של משתנה משתמשים באופרטור &. x y

  9. מצביעים • מה יחזירו &x ו&y . x5000 y5004

  10. מצביעים • ניתן להגדיר משתנים שסוגם הוא מצביע. • משתנים כאלה מחזיקים בתוכם את הכתובות. int main() { int x,y; int* p; p = &x; } x5000 y5004 p9008

  11. מצביעים • כדי לסמן שמצביע לא מצביע לשום מקום נהוג להשים לו NULL • p = NULL; • אפשר לחשוב על משתנה מסוג מצביע כאל חץ: x y p

  12. מצביעים פורמט הדפסה של משתנה מסוג מצביע int main() { int x=7,*p = &x; printf(“Value %d Pointer %p\n”, x, p); } • כדי להדפיס את ערך שאילו מצביע p. printf(“Value %d\n”,*p)

  13. מצביעים • יש לשים לב שאין הצבעה לביטויים ולקבועים &3 &(k+99)

  14. Call by value and call by reference • בכל הפונקציות של c מנגנון העברת של הפונקציות הוא לפי ערך. • נחזור לפונקצית ה swap. • הבעיה הייתה שהחלפת הערכים התבצעה בין הפרמטרים של הפונקציה ולא בין המשתנים עצמם.

  15. Call by reference int main() { int a=10,b=2,x=3,y=5;  swap(&x,&y);  swap(&a,&b); } void swap (int* q,int* p) { int temp = *p; *p = *q; *q = *temp; }

  16. Call by reference • בכדי לממש call by reference יש לבצע את הדברים הבאים: 1 להגדיר את הפרמטרים של הפונקציה כמצביעים void swap(int *p, int *q) 2 להשתמש בגוף הפונקציה בערכים שליהם שמצביעים מצביעים *p = *q; 3 בקריאה לפונקציה להעביר כתובות כארגומנטים swap(&x, &y);

  17. Call by value and call by reference • בכל הפונקציות של c מנגנון העברת של הפונקציות הוא לפי ערך. • נחזור לפונקצית ה swap. • הבעיה הייתה שהחלפת הערכים התבצעה בין הפרמטרים של הפונקציה ולא בין המשתנים עצמם.

  18. Call by reference int main() { int a=10,b=2,x=3,y=5;  swap(&x,&y);  swap(&a,&b); } void swap (int* q,int* p) { int temp = *p; *p = *q; *q = temp; }

  19. Call by reference • בכדי לממש call by reference יש לבצע את הדברים הבאים: 1 להגדיר את הפרמטרים של הפונקציה כמצביעים void swap(int *p, int *q) 2 להשתמש בגוף הפונקציה בערכים שלהם שמצביעים מצביעים *p = *q; 3 בקריאה לפונקציה להעביר כתובות כארגומנטים swap(&x, &y);

  20. הקשר בין מערכים ומצביעים • כאשר אנחנו מגדירים מערך בגדול 20 של שלמים אזי יש לנו 20 משתנים מסוג int בזיכרון. מה הכתובת של משתנים אלו ? • int a[20]; a[0] כמו לכל משתנה גם לאיברי המערך ישנה כתובת. כיצד נגיע לכתובת זו? a[19]

  21. הקשר בין מערכים ומצביעים • ניתן להגיע לכתובות בדרך הרגילה • int *p; • p = &a[0]; • נזכר שהמערך ממוקם בצורה רציפה בזיכרון לכן כתובות איברי המערך הן רציפות למשל: 5000 5004 5008

  22. משמעות שם המערך • פניה לשם המערך נותנת לנו את כתובת המערך שהיא למעשה מצביע לאיבר הראשון במערך. • בשם המערך ניתן להשתמש כדי לקבל את הכתובת הזו לא ניתן לשנות אותו (כלומר הוא מצביע קבוע) • int *p; • p = a; • p מצביע לראש המערך.(את p כמובן שניתן לשנות)

  23. חשבון של מצביעים • ניתן להשתמש בפעולות חיבור וחיסור על כתובות. זה שימושי בעיקר בשילוב עם מערכים. • *(a+i) שקולa[i]; • *(p+i) שקולp[i];

  24. חשבון של מצביעים • מספר דרכים לכתוב לולאה שרצה על מערך: for (i=0; i<N; i++) sum + = a[i]; for (p = a, i=0; i<N; i++) sum + = *(p+i); for (p=a; p<=&a[N-1]; p++) sum + = *p;

  25. חשבון של מצביעים • כיצד ה++ יודע לקדם את המצביע לאיבר הבא ? • הבעיה: המערך יכול להיות של תווים של שלמים או של כל דבר והמרחק בין התאים הוא שונה. • מה המרחק עבור int ? • מה המרחק עבורchar ?

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

  27. העברת מערך לפונקציה • כיצד נכתוב פונקציה שמקבל כערך מערך ומבצעת חישוב על איבריו? • נניח שנרצה לכתוב פונקציה שמקבלת מערך של מספרים ומחזירה את סכום איברי המערך. • העברת מערך לפונקציה מתבצעת למעשה ע"י העברת מצביע לראש המערך. • int sum(int a[], int size); prototype

  28. העברת מערך לפונקציה • a[ ] זהו פשוט מצביע למערך של int. • הפרמטר השני הוא גודל המערך. • מאחר ואנחנו עובדים עם מצביעים אין לנו מידע מהו גודל המערך ולכן נעביר את המידע הזה כפרמטר לפונקציה.

  29. העברת מערך לפונקציה • ההגדרות הבאות שקולות: • int f(float arr[]); • int f(float arr[5]); • int f(float arr[100]); • int f(float *arr);

  30. העברת מערך לפונקציה int sum(int a[], int size) { int i, res = 0; for(i = 0; i < size; i++) res += a[i]; return res; }

  31. העברת מערך לפונקציה Int sum(int *p, int size) { int i, res = 0; for(i = 0; i < size; i++) res += p[i]; return res; }

  32. העברת מערך לפונקציה • כאשר נרצה למנוע א אפשרות של שינוי איברי המערך בפונקציה נעביר את המערך כconst- int sum(const int a[], int size) { int i, res = 0; for(i = 0; i < size; i++) res += a[i]; return res; }

  33. מיון מערכים • המטרה נרצה למיין מערך של מספרים כאשר האיבר הקטן יהיה בתחילת המערך והגדול בסופו. • בעיה חשובה במדעי המחשב • המטרה היא לפתור באופן יעיל ככל הניתן (אנו נציג פיתרון לא יעיל)

  34. מיון מערכים • מציאת אלגוריתם למיון • פסאודו קוד • קוד תיקני ב-C

  35. מיון מערכים-אלגוריתם • האלגוריתם: • נגדיר אלגוריתם בעל N שלבים כאשר בסוף השלב ה-K, K האיברים הקטנים ביותר יהיו ממוינים. • אלגוריתם משני לשלב ה-K • נמצא את האיבר המינימל מבין N-K+1 האיברים הגדולים(אשר נמצאים במערך בין N-(K ונחליף בינו לבין האיבר K.

  36. מיון מערכים – פסאודו קוד min הערך המינימלי min_index האיבר בעל הערך המינמלי SORT(A) N = size(A) For k =1 to N min = A[k] min_index = k for j = k + 1 to N if (A[j] < min) min_index = j; min = A[j] end Swap(A,k,min_index); end מציאת האיבר המינימלי מ- k עד n

  37. מיון מערכים –קוד Void swap(int *, int *); Void Sort(int A[], int size) { int min, min_index, k, j; for(k = 0; k < size; k++) { min = A[k]; min_index = k; for(j = k + 1; j< size;j++) { ….. } swap(A + k, A + min_index); } }

  38. מיון מערכים –קוד for(j= k + 1; j < size; j++) { if (a[j] < min) { min = a[j]; min_index = j; } }

  39. מיון מערכים • מציאת איבר יכולה להיעשות מהר log2(N)) כאשר במערך לא ממוין ייקח למצוא איבר N צעדים

  40. מציאת איבר במערך ממוין – חיפוש בינארי int BinarySearch(const int arr[], int size, int key) { int low, middle, high; low = 0; high = size - 1; while(low <= high) { middle = (low + high) / 2; if (key == arr[middle]) return middle; if (key > arr[middle]) low = middle + 1; else high = middle -1; } return -1; }

  41. איך יראה פיתרון רקורסיבי לבעיה?

  42. מיון מערכים-יעילות • הזמן שייקח לתוכנית זאת למיין הוא סדר גודל של n^2 • האם ניתן לשפר זאת?

  43. מיון בזמן ליניארי- אם הערכים בטווח קטן • בכדי לבצע מיון זה נצטרך באופן כללי שני מערכי עזר אחד למערך הממוין ואחד למערך עזר (כאשר איברי המערך הם מספרים ניתן להסתפק רק במערך העזר) • הרעיון יהיה לספור בעזרת מערך העזר כמה איברים קטנים מאיבר עם ערך k וכך ניתן יהי להכניסו למקום ללא בעיות

  44. מיון בזמן ליניארי- אם הערכים בטווח קטן Counting_Sort(A,B) Set C[N] to 0 For i=1 to SIZE C[A[i]] = C[A[i]] + 1; For i=2 to N C[i] = C[i-1] + C[i] For j=1 to SIZE B[C[A[j]]] = A[j] C[A[j]] = C[A[j]] - 1 כמה איברים מכל סוג כמה איברים קטנים מאיבר מסוג k הכנסה למערך הפלט

  45. void CountSort(const int a[], int b[], int size) { int i; int c[RANGE] = {0}; for(i = 0; i < size; i++) c[a[i]]++; for(i=1; i < RANGE; i++) c[i] += c[i-1]; for(i=0; i < size; i++) { b[c[a[i]]] = a[i]; c[a[i]]--; } return; }

  46. #include <stdio.h> #define SIZE 10 #define RANGE 6 void CountSort(const int a[], int b[], int size); void Print(const int arr[], int size); int main() { int a[SIZE] = {5,3,2,5,5,4,1,1,0,0}, b[SIZE] ={0}; Print(a, SIZE); CountSort(a,b,SIZE); Print(b, SIZE); return 0; }

  47. יעילות • תוכנית זאת תרוץ בזמן ליניארי ב-גודל המערך ובגודל הטווח אך תשתמש במקום עזר

More Related