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

Post on 03-Jan-2016

51 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

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

חזרה -מערכיםחזרה -מערכיםנגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו •

מספר רב של משתנים זהיםמספר רב של משתנים זהים• Type name[SIZE];Type name[SIZE];• Char a[10]; int b[50];Char a[10]; int b[50];

הגודל חייב להיות קבוע.הגודל חייב להיות קבוע.• כאשר כאשר a[k]a[k]פנייה לאיברי המערך מתבצעת ע"י פנייה לאיברי המערך מתבצעת ע"י •

KK ל- ל-00 בין בין SIZE-1SIZE-1אתחול ע"י לולאה או רשימת אתחולאתחול ע"י לולאה או רשימת אתחול•

החלפה בין משתניםהחלפה בין משתנים

נסתכל על התוכנית הבאה:נסתכל על התוכנית הבאה:•int main()int main(){{ int int a,b,x,y,temp;a,b,x,y,temp;

temp = x;temp = x;x = y; x = y; y = temp;y = temp;

temp = a;temp = a;a = b; a = b; b = temp;b = temp;

}}

החלפת הערכיםהחלפת הערכים

החלפת הערכיםהחלפת הערכים

החלפה בין משתניםהחלפה בין משתנים

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

המשתנים. המשתנים. •

החלפה בין משתניםהחלפה בין משתנים

swapswapנכתוב פונקציה כזו בשם נכתוב פונקציה כזו בשם •

void swap(int p, int q)void swap(int p, int q)

{{int tmp = p;int tmp = p;

p = q;p = q;

q = tmp;q = tmp;

}}

החלפה בין משתניםהחלפה בין משתנים

int main()int main(){{ int int a=10,b=2,x=3,y=5,temp;a=10,b=2,x=3,y=5,temp;

swap(x,y);swap(x,y);

swap(a,b);swap(a,b);

}}

החלפה בין משתניםהחלפה בין משתנים

נעקוב אחרי הקריאה נעקוב אחרי הקריאהלפונקציהלפונקציה

swap(x,y);swap(x,y);

33 pp

66 qq

void swap (int q,int p){

int temp = p;p = q; q = temp;

}

66 pp

33 qq

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

עבורו תא באזור כלשהו בזיכרון.עבורו תא באזור כלשהו בזיכרון.

int main()int main()

{{

Int x,y;Int x,y;

}}

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

באופרטור &.באופרטור &.

x

y

מצביעיםמצביעים

. .yy&& ו וxx&&מה יחזירו מה יחזירו •

x 5000

y 5004

מצביעיםמצביעים

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

הכתובות. הכתובות. int main()int main(){{

int x,y;int x,y;int* p; int* p; p = &x; p = &x;

}}

50005000

x 5000

y 5004

p 9008

מצביעיםמצביעיםכדי לסמן שמצביע לא מצביע לשום מקום כדי לסמן שמצביע לא מצביע לשום מקום •

NULLNULLנהוג להשים לו נהוג להשים לו • p = NULL;p = NULL;

אפשר לחשוב על משתנה מסוג מצביע כאל אפשר לחשוב על משתנה מסוג מצביע כאל •x::חץחץ

y

p

מצביעיםמצביעים

int main()int main()

{{

int x=7,*p = &x;int x=7,*p = &x;

printf(“Value %d Pointer %p\n”, x, p);printf(“Value %d Pointer %p\n”, x, p);

}} ..ppכדי להדפיס את ערך שאילו מצביע כדי להדפיס את ערך שאילו מצביע •

printf(“Value %d\n”,*p)printf(“Value %d\n”,*p)

פורמט הדפסה של משתנה מסוג מצביעפורמט הדפסה של משתנה מסוג מצביע

מצביעיםמצביעים

יש לשים לב שאין הצבעה לביטויים יש לשים לב שאין הצבעה לביטויים •ולקבועיםולקבועים

&3&3

&(k+99)&(k+99)

Call by value and call by Call by value and call by referencereference

מנגנון העברת של מנגנון העברת של ccבכל הפונקציות של בכל הפונקציות של •הפונקציות הוא לפי ערך. הפונקציות הוא לפי ערך.

. . swapswapנחזור לפונקצית ה נחזור לפונקצית ה •הבעיה הייתה שהחלפת הערכים התבצעה הבעיה הייתה שהחלפת הערכים התבצעה •

בין הפרמטרים של הפונקציה ולא בין בין הפרמטרים של הפונקציה ולא בין המשתנים עצמם.המשתנים עצמם.

Call by referenceCall by referenceint main()int main(){{ int int a=10,b=2,x=3,y=5;a=10,b=2,x=3,y=5;

swap(&x,&y);swap(&x,&y);

swap(&a,&b);swap(&a,&b);

}}void swap (int* q,int* p)void swap (int* q,int* p){{

int temp = *p;int temp = *p;*p = *q; *p = *q; *q = *temp;*q = *temp;

}}

Call by referenceCall by reference בכדי לממש בכדי לממשcall by referencecall by reference יש לבצע את יש לבצע את

הדברים הבאים:הדברים הבאים:

להגדיר את הפרמטרים של הפונקציה כמצביעים להגדיר את הפרמטרים של הפונקציה כמצביעים11

void swap(void swap(int *p, int *qint *p, int *q))

להשתמש בגוף הפונקציה בערכים שליהם להשתמש בגוף הפונקציה בערכים שליהם 22שמצביעים מצביעיםשמצביעים מצביעים

*p = *q;*p = *q;

בקריאה לפונקציה להעביר כתובות כארגומנטים בקריאה לפונקציה להעביר כתובות כארגומנטים33

swapswap(&x, &y);(&x, &y);

Call by value and call by Call by value and call by referencereference

מנגנון העברת של מנגנון העברת של ccבכל הפונקציות של בכל הפונקציות של •הפונקציות הוא לפי ערך. הפונקציות הוא לפי ערך.

. . swapswapנחזור לפונקצית ה נחזור לפונקצית ה •הבעיה הייתה שהחלפת הערכים התבצעה הבעיה הייתה שהחלפת הערכים התבצעה •

בין הפרמטרים של הפונקציה ולא בין בין הפרמטרים של הפונקציה ולא בין המשתנים עצמם.המשתנים עצמם.

Call by referenceCall by referenceint main()int main(){{ int int a=10,b=2,x=3,y=5;a=10,b=2,x=3,y=5;

swap(&x,&y);swap(&x,&y);

swap(&a,&b);swap(&a,&b);

}}void swap (int* q,int* p)void swap (int* q,int* p){{

int temp = *p;int temp = *p;*p = *q; *p = *q; *q = temp;*q = temp;

}}

Call by referenceCall by reference יש לבצע את יש לבצע את call by referencecall by referenceבכדי לממש בכדי לממש •

הדברים הבאים:הדברים הבאים:

להגדיר את הפרמטרים של הפונקציה כמצביעים להגדיר את הפרמטרים של הפונקציה כמצביעים11

void swap(void swap(int *p, int *qint *p, int *q))

להשתמש בגוף הפונקציה בערכים שלהם להשתמש בגוף הפונקציה בערכים שלהם 22שמצביעים מצביעיםשמצביעים מצביעים

*p = *q;*p = *q;

בקריאה לפונקציה להעביר כתובות כארגומנטים בקריאה לפונקציה להעביר כתובות כארגומנטים33

swapswap(&x, &y);(&x, &y);

הקשר בין מערכים ומצביעיםהקשר בין מערכים ומצביעים של של 2020כאשר אנחנו מגדירים מערך בגדול כאשר אנחנו מגדירים מערך בגדול •

intint משתנים מסוג משתנים מסוג 2020שלמים אזי יש לנו שלמים אזי יש לנו בזיכרון. מה הכתובת של משתנים אלו ?בזיכרון. מה הכתובת של משתנים אלו ?

• int a[20];int a[20];

a[19]

a[0]כמו לכל משתנה גם

לאיברי המערך ישנה כתובת. כיצד נגיע

לכתובת זו?

הקשר בין מערכים ומצביעיםהקשר בין מערכים ומצביעים

ניתן להגיע לכתובות בדרך הרגילהניתן להגיע לכתובות בדרך הרגילה•• int *p;int *p;• p = &a[0];p = &a[0];

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

5000רציפות למשל:רציפות למשל:50045008

משמעות שם המערךמשמעות שם המערך

פניה לשם המערך נותנת לנו את כתובת פניה לשם המערך נותנת לנו את כתובת •המערך שהיא למעשה מצביע לאיבר המערך שהיא למעשה מצביע לאיבר

הראשון במערך. הראשון במערך. בשם המערך ניתן להשתמש כדי לקבל את בשם המערך ניתן להשתמש כדי לקבל את •

(כלומר (כלומר לא ניתן לשנות אותו לא ניתן לשנות אותו הכתובת הזו הכתובת הזו הוא מצביע קבוע)הוא מצביע קבוע)

• int *p;int *p;• p = a; p = a;

•pp.את (את מצביע לראש המערך. מצביע לראש המערך)pp כמובן כמובן שניתן לשנות)שניתן לשנות)

חשבון של מצביעיםחשבון של מצביעים

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

..מערכיםמערכים

• *(a+i)*(a+i) שקולשקול a[i];a[i];• *(p+i)*(p+i) שקולשקול p[i];p[i];

חשבון של מצביעיםחשבון של מצביעיםמספר דרכים לכתוב לולאה שרצה על מערך:מספר דרכים לכתוב לולאה שרצה על מערך:•

for (i=0; i<N; i++)for (i=0; i<N; i++)sum + = a[i];sum + = a[i];

for (p = a, i=0; i<N; i++)for (p = a, i=0; i<N; i++)sum + = *(p+i);sum + = *(p+i);

for (p=a; p<=&a[N-1]; p++)for (p=a; p<=&a[N-1]; p++)sum + = *p;sum + = *p;

חשבון של מצביעיםחשבון של מצביעים

כיצד ה++ יודע לקדם את המצביע לאיבר כיצד ה++ יודע לקדם את המצביע לאיבר •הבא ? הבא ?

: המערך יכול להיות של תווים של : המערך יכול להיות של תווים של הבעיההבעיה•שלמים או של כל דבר והמרחק בין התאים שלמים או של כל דבר והמרחק בין התאים

הוא שונה.הוא שונה. ? ?intintמה המרחק עבור מה המרחק עבור • ? ? charchar מה המרחק עבורמה המרחק עבור•

חשבון של מצביעיםחשבון של מצביעים

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

והסיבה שמגדירים את סוג האיבר שאילו והסיבה שמגדירים את סוג האיבר שאילו מצביעים.מצביעים.

המקום השני שבו אנו משתמשים בסוג המקום השני שבו אנו משתמשים בסוג •שאליו מצביעים הוא בשימוש ב-*שאליו מצביעים הוא בשימוש ב-*

העברת מערך לפונקציההעברת מערך לפונקציה

כיצד נכתוב פונקציה שמקבל כערך מערך כיצד נכתוב פונקציה שמקבל כערך מערך •ומבצעת חישוב על איבריו? ומבצעת חישוב על איבריו?

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

איברי המערך. איברי המערך. העברת מערך לפונקציה מתבצעת למעשה העברת מערך לפונקציה מתבצעת למעשה •

ע"י העברת מצביע לראש המערך. ע"י העברת מצביע לראש המערך. • int sum(int a[], int size);int sum(int a[], int size);

prototype

העברת מערך לפונקציההעברת מערך לפונקציה

•aa[ ][ ] זהו פשוט מצביע למערך של זהו פשוט מצביע למערך של intint . .הפרמטר השני הוא גודל המערך. הפרמטר השני הוא גודל המערך. •מאחר ואנחנו עובדים עם מצביעים אין לנו מאחר ואנחנו עובדים עם מצביעים אין לנו •

מידע מהו גודל המערך ולכן נעביר את מידע מהו גודל המערך ולכן נעביר את המידע הזה כפרמטר לפונקציה.המידע הזה כפרמטר לפונקציה.

העברת מערך לפונקציההעברת מערך לפונקציה

ההגדרות הבאות שקולות:ההגדרות הבאות שקולות:•• int f(float arr[]);int f(float arr[]);• int f(float arr[5]);int f(float arr[5]);• int f(float arr[100]);int f(float arr[100]);• int f(float *arr);int f(float *arr);

העברת מערך לפונקציההעברת מערך לפונקציה

int sum(int a[], int size)int sum(int a[], int size){{

int i, res = 0;int i, res = 0;for(i = 0; i < size; i++)for(i = 0; i < size; i++) res += a[i];res += a[i];return res;return res;

}}

העברת מערך לפונקציההעברת מערך לפונקציה

Int sum(int *p, int size)Int sum(int *p, int size){{

int i, res = 0;int i, res = 0;for(i = 0; i < size; i++)for(i = 0; i < size; i++) res += p[i];res += p[i];return res;return res;

}}

העברת מערך לפונקציההעברת מערך לפונקציה

כאשר נרצה למנוע א אפשרות של שינוי איברי המערך כאשר נרצה למנוע א אפשרות של שינוי איברי המערך •--constconstבפונקציה נעביר את המערך כבפונקציה נעביר את המערך כ

int sum(const int a[], int size)int sum(const int a[], int size){{

int i, res = 0;int i, res = 0;for(i = 0; i < size; i++)for(i = 0; i < size; i++) res += a[i];res += a[i];return res;return res;

}}

מיון מערכיםמיון מערכים

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

בסופו.בסופו.

בעיה חשובה במדעי המחשבבעיה חשובה במדעי המחשב•

המטרה היא לפתור באופן יעיל ככל הניתן (אנו המטרה היא לפתור באופן יעיל ככל הניתן (אנו •נציג פיתרון לא יעיל)נציג פיתרון לא יעיל)

מיון מערכיםמיון מערכים

מציאת אלגוריתם למיוןמציאת אלגוריתם למיון•

פסאודו קודפסאודו קוד•

CCקוד תיקני ב-קוד תיקני ב-•

מיון מערכים-אלגוריתםמיון מערכים-אלגוריתם

האלגוריתם:האלגוריתם:• שלבים כאשר בסוף שלבים כאשר בסוף NNנגדיר אלגוריתם בעל נגדיר אלגוריתם בעל •

האיברים הקטנים ביותר יהיו האיברים הקטנים ביותר יהיו KK, , KKהשלב ה-השלב ה-ממוינים.ממוינים.

KKאלגוריתם משני לשלב ה-אלגוריתם משני לשלב ה-• N-K+1N-K+1נמצא את האיבר המינימל מבין נמצא את האיבר המינימל מבין •

--NNהאיברים הגדולים(אשר נמצאים במערך בין האיברים הגדולים(אשר נמצאים במערך בין (K(K ונחליף בינו לבין האיבר ונחליף בינו לבין האיבר KK..

מיון מערכים – פסאודו קודמיון מערכים – פסאודו קודSORT(A)SORT(A)N = size(A)N = size(A)For k =1 to NFor k =1 to N

min = A[k]min = A[k]min_index = kmin_index = kfor j = k + 1 to N for j = k + 1 to N

if (A[j] < min)if (A[j] < min) min_index = j; min = A[j]min_index = j; min = A[j]

endendSwap(A,k,min_index);Swap(A,k,min_index);

endend

מציאת האיבר n עד kהמינימלי מ-

minהערך המינימלי

min_indexהאיבר

בעל הערך המינמלי

מיון מערכים –קודמיון מערכים –קודVoid swap(int *, int *);Void swap(int *, int *);Void Sort(int A[], int size)Void Sort(int A[], int size){{

int min, min_index, k, j;int min, min_index, k, j;for(k = 0; k < size; k++)for(k = 0; k < size; k++){{ min = A[k]; min_index = k;min = A[k]; min_index = k;

for(j = k + 1; j< size;for(j = k + 1; j< size; j++)j++){{

……....}}swap(A + k, A + min_index);swap(A + k, A + min_index);

}}}}

מיון מערכים –קודמיון מערכים –קוד

for(j= k + 1; j < size; j++)for(j= k + 1; j < size; j++){{

if (a[j] < min)if (a[j] < min){{

min = a[j];min = a[j];min_index = j;min_index = j;

}}}}

מיון מערכיםמיון מערכים

) ) loglog22(N)(N)מציאת איבר יכולה להיעשות מהר מציאת איבר יכולה להיעשות מהר •

NNכאשר במערך לא ממוין ייקח למצוא איבר כאשר במערך לא ממוין ייקח למצוא איבר צעדיםצעדים

מציאת איבר במערך ממוין – חיפוש מציאת איבר במערך ממוין – חיפוש בינאריבינארי

int BinarySearch(const int arr[], int size, int key)int BinarySearch(const int arr[], int size, int key){{

int low, middle, high;int low, middle, high;low = 0; low = 0; high = size - 1;high = size - 1;while(low <= high)while(low <= high){{

middle = (low + high) / 2;middle = (low + high) / 2;if (key == arr[middle])if (key == arr[middle])

return middle;return middle;if (key > arr[middle])if (key > arr[middle])

low = middle + 1;low = middle + 1;elseelse

high = middle -1;high = middle -1;}}return -1;return -1;

}}

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

מיון מערכים-יעילותמיון מערכים-יעילות

הזמן שייקח לתוכנית זאת למיין הוא סדר גודל הזמן שייקח לתוכנית זאת למיין הוא סדר גודל •n^2n^2של של

האם ניתן לשפר זאת?האם ניתן לשפר זאת?•

מיון בזמן ליניארי- אם הערכים בטווח מיון בזמן ליניארי- אם הערכים בטווח קטןקטן

בכדי לבצע מיון זה נצטרך באופן כללי שני בכדי לבצע מיון זה נצטרך באופן כללי שני •מערכי עזר אחד למערך הממוין ואחד למערך מערכי עזר אחד למערך הממוין ואחד למערך

עזר (כאשר איברי המערך הם מספרים ניתן עזר (כאשר איברי המערך הם מספרים ניתן להסתפק רק במערך העזר)להסתפק רק במערך העזר)

הרעיון יהיה לספור בעזרת מערך העזר כמה הרעיון יהיה לספור בעזרת מערך העזר כמה • וכך ניתן יהי וכך ניתן יהי kkאיברים קטנים מאיבר עם ערך איברים קטנים מאיבר עם ערך

להכניסו למקום ללא בעיותלהכניסו למקום ללא בעיות

מיון בזמן ליניארי- אם הערכים בטווח מיון בזמן ליניארי- אם הערכים בטווח קטןקטן

Counting_Sort(A,B)Counting_Sort(A,B)

Set C[N] to 0Set C[N] to 0

For i=1 to SIZEFor i=1 to SIZEC[A[i]] = C[A[i]] + 1;C[A[i]] = C[A[i]] + 1;

For i=2 to NFor i=2 to N

C[i] = C[i-1] + C[i]C[i] = C[i-1] + C[i]

For j=1 to SIZEFor j=1 to SIZE

B[C[A[j]]] = A[j]B[C[A[j]]] = A[j]

C[A[j]] = C[A[j]] - 1C[A[j]] = C[A[j]] - 1

כמה איברים מכל סוג

כמה איברים קטנים מאיבר

kמסוג הכנסה למערך

הפלט

void CountSort(const int a[], int b[], int size)void CountSort(const int a[], int b[], int size){{

int i;int i;int c[RANGE] = {0};int c[RANGE] = {0};

for(i = 0; i < size; i++)for(i = 0; i < size; i++)c[a[i]]++;c[a[i]]++;

for(i=1; i < RANGE; i++)for(i=1; i < RANGE; i++)c[i] += c[i-1];c[i] += c[i-1];

for(i=0; i < size; i++)for(i=0; i < size; i++){{

b[c[a[i]]] = a[i];b[c[a[i]]] = a[i];c[a[i]]--;c[a[i]]--;

}}return;return;

}}

#include <stdio.h>#include <stdio.h>

#define SIZE 10#define SIZE 10#define RANGE 6#define RANGE 6

void CountSort(const int a[], int b[], int size);void CountSort(const int a[], int b[], int size);void Print(const int arr[], int size);void Print(const int arr[], int size);

int main()int main(){{

int a[SIZE] = {5,3,2,5,5,4,1,1,0,0}, b[SIZE] ={0};int a[SIZE] = {5,3,2,5,5,4,1,1,0,0}, b[SIZE] ={0};

Print(a, SIZE);Print(a, SIZE);CountSort(a,b,SIZE);CountSort(a,b,SIZE);Print(b, SIZE);Print(b, SIZE);return 0;return 0;

}}

יעילותיעילות

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

top related