Professional Documents
Culture Documents
הרצאה 8
הרצאה 8
ש ק פ ים :ד ר ׳ ע פ ר ש י ר ,ע וד כ ן ע ״ י א י ת י ש ר ו ן
2
רשימות מקושרות
Linked lists
3
רשימה מקושרת :בסיס
• מבנה נתונים שאיבריו מסודרים באופן לינארי
4
רשימה מקושרת חד-כיוונית
data=17 • רשימה מקושרת הינה שרשרת של משתנים
next=0xdff268 בזיכרון כאשר כל משתנה מצביע למשתנה הבא
בשרשרת
data=200
– סוף הרשימה מיוצג ע"י מצביע לNULL-
next=0xdef4c4
• רשימה מקושרת הינה מבנה נתונים המאפשר
data=-15
שמירת ערכים בזיכרון
next=0x43ba12
– דוגמא נוספת למבנה נתונים :מערך
data=8
• רשימה מקושרת מאפשרת:
– שמירה של מספר ערכים שאינו קבוע
next=0x0
– הכנסה והוצאה של משתנים מכל מקום ברשימה
– חיבור וחלוקת רשימות
5
מערך לעומת רשימה מקושרת
רשימה מקושרת מע ר ך
שימוש בשטח זכרון שאינו מבנה נתונים המשתמש
בהכרח רציף בשטח זיכרון רציף
גישה מהירה לתאי המערך גישה איטית לאיברי הרשימה
)לכתיבה/קריאה( אם המערך לצורך קריאה/כתיבה )נדרש
מעבר על כל האיברים במקרה ממויין
הגרוע(
כדי להגדיל את המערך ,יש הוספת/הורדת איברים הינה
לחפש מקום חדש ולהעתיק מהירה – נדרשת הקצאת מקום
לאיבר אחד נוסף את כל איבריוrealloc :
פעולה יקרה!
6
מבנים המתייחסים לעצמם
typedef struct Bday_t {
char* name;
Date date;
struct Bday_t *next;
} Bday;
int main(void){
Bday dt1, dt2, *pdt;
set_day(dt1.date, 31); set_month(dt1.date, 12);
set_year(dt1.date, 1992);
set_day(dt2.date, 1); set_month(dt2.date, 1);
set_year(dt2.date, 1993);
pdt = &dt1;
dt1.next = &dt2;
dt2.next = NULL;
printf("Year in dt1: %d\nYear in dt2: %d\n",
get_year(dt1.date), get_year(dt1.next->date));
return 0;
} 7
מבנים המתייחסים לעצמם:מימוש
:• נבחן את המבנה הבא
next; struct node {
typedef
int data;
} struct
*Node;node *next;
} Node;
8
דוגמא :שמירת ימי הולדת
• משימה :כתבו תכנית המקבלת רשימת תאריכים
מהמשתמשת ומדפיסה אותם
newNode
• פתרון:
next=0x0ffef6
day=9
– ניצור רשימה מקושרת של תאריכים
– בכל פעם שנקלוט תאריך חדש נוסיפה
data
"month="JUN
list
0x0ffef6 next=0x0ffef6 next=0x0ffef6
day=9 day=9
data
data
"month="JUN "month="JUN
year=1962 year=1962
9
פיתרון
#include <stdlib.h>
#include <string.h>
#include "Date.h"
10
פיתרון
Bday* addNode(const char* name, Date d, Bday* head) {
Bday* ptr = (Bday*)malloc(sizeof(Bday));
if(!ptr)
return NULL;
ptr->name = strdup(name);
ptr->date = create_date();
set_day(ptr->date, get_day(d));
set_month(ptr->date, get_month(d));
set_year(ptr->date, get_year(d));
ptr->next = head;
return ptr;
}
11
פיתרון
Bday* remove_bday(Bday* head, Bday* node) {
if(head == NULL)
return NULL;
Bday *curr=head->next, *prev=head;
if(!strcmp(head->name, node->name)) {
free(head->name); destroy_date(head->date); free(head);
return curr;
}
while(curr && strcmp(node->name, curr->name)) {
prev=curr; curr=curr->next;
}
if(curr) {
prev->next = curr->next;
free(curr->name); destroy_date(curr->date); free(curr);
}
return head;
}
12
פיתרון
void destroyList(Bday* head) {
while(head) {
head = remove_node(head, head);
}
}
13
שימוש
int main(void) {
Bday *head = NULL, *ptr;
Date date;
char* name=NULL;
// Function birthdayRead is implemented elsewhere
while (birthdayRead(name, date)) {
head = addNode(name, date, head);
free(name);
date_destroy(date);
}
for(ptr=head ; ptr!=NULL ; ptr=ptr->next)
birthdayPrint(ptr); // Function birthdayPrint
// is implemented elsewhere...
destroyList(head);
return 0;
}
14
הערות
15
סיכום :רשימה מקושרת
ניתן ליצור רשימות מקושרות ע"י הוספת מצביע למבנה •
בתוך אותו המבנה
רשימות מקושרות אינן מוגבלות בגודלן ומאפשרות •
הכנסה נוחה של איברים באמצע הרשימה
את האיברים ברשימה יש להקצות דינאמית ולוודא •
שישוחררו
במימוש רשימה מקושרת ניתן ואף מומלץ להוסיף איבר •
דמה בתחילתה
16
מחסניות
Stacks
17
מחסנית :הגדרה
• מחסנית היא מבנה נתונים לינארי בו הוצאה והכנסה של
איברים יכולה להתרחש רק מראש המבנה
• עיקרון המחסנית:
האחרון שנכנס הוא הראשון לצאת
18
Last In First Out
E top
D top D D top
C top C C C
B top B B B B
A top A A A A A
19
מחסנית :הגדרת פעולות
20
push
21
pop
22
מימוש מחסנית
איך נממש?
23
מימוש מחסנית
איך נממש?
• מערך עם מצביע לראש המחסנית
top
• רשימה מקושרת
top 24
C ממשק מחסנית בשפת
#ifndef STACK_H
#define STACK_H
#include <stdbool.h>
typedef void* Element;
typedef struct Stack* Stack;
26
תור :הגדרה
• תור הוא מבנה נתונים לינארי בו הכנסת איברים
מתרחשת בקצה אחד והוצאת האיברים מתרחשת
מן הקצה השני
• בתור עצמו – המידע מעובד בסדר בו התקבל
• עיקרון התור :הראשון שנכנס הוא הראשון לצאת
27
First In First Out
28
שימושים בתור
• אחד ממבני הנתונים היותר שימושיים לעיבוד מידע
במערכות הפעלה וניהול רשתות
– ניהול תור בקשות אל מול משאבים
– התאמה בין ייצור מהיר של מידע לצריכתו )מעבד/מדפסת(
29
תור :הגדרת פעולות
30
enqueue (push)
31
dequeue (pop)
32
מימוש תור
איך נממש?
33
מימוש תור
איך נממש?
• מערך עם מצביעים לראש ולסוף התור
front rear
#ifndef QUEUE_H
#define QUEUE_H
#include <stdbool.h>
typedef void* Element;
typedef struct Queue* Queue;