1 / 32

מבוא למדעי המחשב

מבוא למדעי המחשב. רשומות structures. רשומות structures. רשומות הן מבני נתונים שמאפשרים לאגד ביחד נתונים מטיפוסים שונים. דוגמא: תאריך struct date { char day ; char month ; int year ; } today , birthday ; שימו לב: המשתנים לא בהכרח ממוקמים בזיכרון ברצף!.

scarolina
Télécharger la présentation

מבוא למדעי המחשב

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. מבוא למדעי המחשב רשומות structures

  2. רשומות structures • רשומות הן מבני נתונים שמאפשרים לאגד ביחד נתונים מטיפוסים שונים. • דוגמא: תאריך struct date { char day; char month; int year; } today, birthday; • שימו לב: המשתנים לא בהכרח ממוקמים בזיכרון ברצף! תג אופציונאלי המאפשר להתייחס לרשומות מהסוג שהוגדר לעיל בעתיד. שדות ברשומה (members) הגדרת משתנים מטיפוס זה

  3. רשומות structures • דוגמא: תאריך struct date { char day; char month; int year; } ; struct date today, birthday; • אתחול רשומה ע"י פירוט מאתחלים לכל שדותיה: struct date tomorrow={6,6,2006};

  4. רשומות structures • ניתן לגשת לשדות של רשומה ע"י שימוש באופרטור ".": struct-name.member • דוגמא: struct date today={5,6,2006}; : printf(“%d %d %d”, today.day, today.month, today.year); today.year++; today.month=6; :

  5. רשומות structures • ניתן לקנן רשומות: struct student{ char name[20]; int year; struct date birthday; }; : struct student st1; : st1.year=1; st1.birthday.year=1975;

  6. פעולות על רשומות • העתקה והשמה כיחידה אחת • כתובת (&) • גישה לשדה • העברה כפרמטר לפונקציה / החזרה כערך מוחזר של פונקציה לא ניתן להשוות שתי רשומות (בפעולה אחת)!

  7. העברת רשומות לפונקציה • העברה by value • העברת כתובת by value • העברת ערך אחרי ערך ← העברת רכיבי הרשומה

  8. רשומות structures • העברת רכיבים: struct date makedate (char day, char month, int year) { struct date temp; temp.day=day; temp.month=month; temp.year=year; return temp; } • השימוש בפונקציה makedate: struct student st1; struct date today; : st1.birthday=makedate(31,10,1975); today=makedate(8,6,2006);

  9. רשומות structures • העברת רשומה by value: struct date nextDay (struct date d) { d.day++; if (d.day > numDaysInMonth (d.month, d.year)){ d.day=1; d.month++; if (d.month > DEC){ d.month=JAN; d.year++; } } return d; } • קריאה לפונקציה: struct date today={8,6,2006}, tomorrow; : tomorrow=nextDay(today);

  10. רשומות structures • העברת כתובת הרשומה by value: void nextDay (struct date *d) { (*d).day++; if ((*d).day > numDaysInMonth ((*d).month, (*d).year)){ (*d).day=1; (*d).month++; if ((*d).month > DEC){ (*d).month=JAN; (*d).year++; } } return; } • קריאה לפונקציה: struct date today={8,6,2006}; : nextDay(&today); הסוגריים הכרחיים!

  11. רשומות structures • קיצור כתיבה: void nextDay (struct date *d) { d->day++; if (d->day > numDaysInMonth (d->month, d->year)){ d->day=1; d->month++; if (d->month > DEC){ d->month=JAN; d->year++; } } return; } • באופן כללי: אם p מצביע לרשומה, אזי p->member מתייחס לשדה member ברשומה אליה מצביע p.

  12. רשומות structures הערות: 1. אם מוגדר struct student st1, *stp=&st1; אזי הביטויים הבאים שקולים: • st1.birthday.year • (st1.birthday).year • stp->birthday.year • (stp->birthday).year 2. העתקת רשומות המכילות מערכים: אם רשומה מכילה מערך, אזי העתקת רשומה תגרום להעתקת כתובת המערך ולא המערך עצמו (גם כאן, יש לכתוב פונקציה שתעתיק רשומות עם מערכים).

  13. typedef - תזכורת • כאשר מוגדרת רשומה בתכנית שימושי ונוח להיעזר בהגדרות טיפוסים. • למשל, ההגדרה typedef struct date { char day; char month; int year; } Date; מאפשרת להגדיר מאוחר יותר טיפוסים מסוג הרשומה כך: Date d, birthday; • הערה: התג date הופך כאן למיותר. בהמשך כשנדון ברשומות המתייחסות לעצמן, נראה למה הוא נחוץ.

  14. מערכים של רשומות • דוגמת מוטיבציה: נרצה לכתוב תכנית בשפת C הסופרת את מספר המופעים של מילים שמורות ב- C בקובץ אותו היא מקבלת כקלט. • 2 אופציות לפתרון: (1) מערכים (2) רשומות • (1) ע"י מערכים: char *keywords[NKEYS]={“auto”,”break”,”case”,”char”,…}; int keycount[NKEYS]={0}; מערך בגודל NKEYS של מחרוזות שמאותחל להכיל את המילים השמורות. מערך לשמירת מספר המופעים של כל מילה שמורה. במקום ה- i במערך זה יאוחסן מספר המופעים של המילה שנמצאת במקום ה- i של המערך הקודם.

  15. מערכים של רשומות • (2) ע"י רשומות: struct key{ char *keyword; int count; } keytable[NKEYS]={ {“auto”,0},{“break”,0},{“case”,0},{“char”,0}… }; גישה לתא במערך: keytable[n].count++; הדפסת המערך: printf(“%d %s\n”, keytable[i].count, keytable[i].keyword);

  16. רשימה מקושרת Linked list האם ניתן להגדיר רשומה כאשר אחד השדות של הרשומה הוא רשומה מטיפוס זהה לרשומה המקורית? לא! ברגע שנעשה דבר שכזה נוצר מבנה מעגלי אין סופי! אבל... ניתן להגדיר רשומה שאחד השדות בה הוא מטיפוס מצביע לרשומה עצמה!

  17. content content content next next next NULL 5 3 11 Node Node Node רשימה מקושרת Linked list • דוגמא: typedef struct node{ int content; struct node *next; } Node;

  18. רשימה מקושרת Linked list מערכים ↔ רשימות מקושרות: • אברי מערכים בשפת C ממוקמים בזיכרון באופן רציף. אברי רשימה מקושרת לא חייבים לשבת בזיכרון באופו רציף. • כאשר מגדירים מערך (בזמן כתיבת התכנית) יש להגדיר את אורכו. גם אם מקצים את אורך המערך בזמן ריצה יש לדעת את גודלו לפני הקצאתו. ברשימה מקושרת אין צורך לקבוע את גודלה מראש (ניתן להקצות זיכרון באופן דינאמי בזמן ריצה ע"י malloc). דוגמא: תכנית הקולטת נתונים (למשל מספרים) עד EOF ללא שום אינידיקציה על מספר הנתונים (עד ל- EOF).

  19. רשימה מקושרת - דוגמא int main() { int input; Node *list=NULL; /* read numbers until scanf fails */ while (scanf("%d", &input) == 1) { list=insert(input,list); } print_list(list); free_list(list); return 0; } /* insertion_sort-lists.c */ /* sort a sequence of numbers. uses linked lists. */ #include <stdio.h> #include <stdlib.h> enum {FALSE, TRUE}; typedef struct node{ int contents; struct node *next; } Node; Node* insert (int input,Node *list); void free_list (Node *list); void print_list (Node *list);

  20. רשימה מקושרת - דוגמא Node *insert (int input , Node *list) { Node *p,*q; /* allocate memory for new record */ if ((p = (Node *)malloc (sizeof (Node))) == NULL) { printf ("Cannot allocate memory\n"); exit (1); } p->contents=input; /* store input in new record */ /* first, handle the case where input should be first element */ if (list==NULL || /* this is the first element */ list->contents > input) { /* input should be first element */ p->next=list; return p; } else { /* search list for the right location */ q=list; while (q->next!=NULL && q->next->contents < input) { q=q->next; } p->next=q->next; q->next=p; return list; } }

  21. רשימה מקושרת - דוגמא void free_list(Node *list) { Node *p; while (list!=NULL){ p=list->next; free(list); list=p; } } void print_list(Node *list) { Node *p; for (p=list; p!=NULL; p=p->next){ printf ("%4d", p->contents); } printf ("\n"); }

  22. פעולות על מבני נתונים • הכנסה insert • הוצאה remove • הדפסה print

  23. ארגון מבני נתונים – סדר כניסה/יציאה • תור queue FIFO: First In First Out • מחסנית stack LIFO: Last In First Out

  24. int main() { Contents input; char command; Queue *q=makeQueue(); /* read numbers until scanf fails */ while ((command=getchar()) != EOF){ switch (command){ case 'i': scanf("%d\n", &input); if (!insertq(q,input)) { printf ("Cannot allocate memory.\n"); } break; case 'r': if (removeq(q, &input)) { printf ("Removed %d from queue.\n", input); } break; default: printf ("Illegal operation %c.\n", command); break; } /* switch */ printQueue (q); } freeQueue (q); return 0; } Queue /* queue.c */ /* implement a queue. uses linked lists. */ #include <stdio.h> #include <stdlib.h> enum {FALSE, TRUE} ; typedef int Contents; typedef int boolean; typedef struct node { Contents contents; struct node *next; } Node; typedef struct que { Node *first; Node *last; int size; } Queue; Queue *makeQueue (void); boolean insertq (Queue *q, Contents contents); boolean removeq (Queue *q, Contents *contents); void freeQueue (Queue *q); void printQueue (Queue *q);

  25. Queue Queue *makeQueue (void) { Queue *q; q = (Queue *) malloc (sizeof (Queue)); q->first = q->last = NULL; q->size = 0; return q; }

  26. Queue void freeQueue (Queue *q) { Node *p1, *p2 = q->first; while (p2 != NULL) { p1 = p2->next; free (p2); p2 = p1; } } void printQueue (Queue *q) { Node *p; printf ("print_queue (%d)\n", q->size); for (p = q->first; p != NULL; p = p->next) { printf ("%4d", p->contents); } printf ("\n"); }

  27. Queue boolean insertq (Queue *q, Contents contents) { Node *p; printf ("insertq %d (%d)\n", contents, q->size); if ((p = (Node *) malloc (sizeof (Node))) == NULL) { return FALSE; } else { p->contents = contents; /* store contents */ p->next = NULL; if (q->last == NULL) { /* q is empty */ q->first = p; /* p points to first element */ } else { q->last->next = p; /* add p as last element */ } q->last = p; /* update q structure */ (q->size)++; return TRUE; } }

  28. Queue boolean removeq (Queue *q, Contents *contents) { Node *p = q->first; /* record the record to be removed, so it can be freed */ if (q->first == NULL ) { /* queue is empty */ return FALSE; } else { *contents = q->first->contents; /* return contents */ q->first = q->first->next; /* skip over first element in the list */ if (q->first == NULL) { /* if this was the only cell */ q->last = NULL; /* update the q structure */ } (q->size)--; free (p); return TRUE; } }

  29. 20 34 4 56 11 14 5- 9 58- 20 21 21- 0 1 2 23 6 6- 12 רקורסיה – דוגמא מציאת איבר מקסימלי בעץ בינארי:

  30. רקורסיה – דוגמא מציאת איבר מקסימלי בעץ בינארי: typedef struct node { int content; struct node *left; struct node *right; } Node;

  31. רקורסיה – דוגמא מציאת איבר מקסימלי בעץ בינארי: הנחות: • לכל צומת בעץ יש בדיוק שני בנים או אין בנים כלל. • השורש אינו NULL (כלומר, קיים לפחות צומת אחד בעץ).

  32. רקורסיה – דוגמא int findmax (Node *node) { int left, right, maxlr, max; if (node->left==NULL) return node->content; left=findmax(node->left); right=findmax(node->right); maxlr= left >right ? left:right; max= maxlr>node->content ? maxlr:node->content; return max; }

More Related