מערכים, מטריצות דלילות, ורשימות מקושרות
DESCRIPTION
Lecture2 of Geiger & Itai’s slide brochure www.cs.technion.ac.il/~dang/courseDS. מערכים, מטריצות דלילות, ורשימות מקושרות. חומר קריאה לשיעור זה. Chapter 11.2– Linked lists (204 – 213). Geiger & Itai, 2001. מערך כטיפוס נתונים אבסטרקטי. מערך מוגדר ע"י הפעולות הבאות : - PowerPoint PPT PresentationTRANSCRIPT
Arrays+lists
, דלילות, מטריצות מערכיםמקושרות ורשימות
Chapter 11.2– Linked lists (204 – 213)
זה לשיעור קריאה חומר
Lecture2 of Geiger & Itai’s slide brochure
www.cs.technion.ac.il/~dang/courseDS
Geiger & Itai, 2001
cs,Technion
2Arrays+lists נתונים כטיפוס מערךאבסטרקטי
" הבאות הפעולות י ע מוגדר :מערך
create(type,I) – מחזיר מערךAשל איברים כאשר האינדקסים הם הקבוצה type מטיפוס. I הסופית
get(A,i) – מחזיר את הערך של האיבר עם. A בתוך i I אינדקס
store(A,i,e) – מאחסן במערך A , תחת. e את ערך הביטוי, i I אינדקס
כללים הנשמרים ע"י הפעולות:
.(type)כל הערכים במערך מאותו טיפוס, והוא נקבע בהכרזה •
.iהאחרון שנשמר לפי אינדקס , הוא הערךiהערך המאוחזר לפי אינדקס •
מחזיר ערך בלתי מוגדר אם מעולם לא אוחסן ערך iאחזור לפי אינדקס •לפי אינדקס זה.
I
האינדקסים הם cבשפת I={0,…,n-1}הקבוצה
A[i] (get) אחזר
A[i] = e (store)שמור
cs,Technion
3Arrays+lists
למערך (1 ) מימושים. )O)1 כל הפעולות מתבצעות בזמן אזור זיכרון רצוף:
address
102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260
102421024110240
1026110262
base
0123456789
1011121314151617
offset
מתבססות על חישובי כתובות הפעולות:
Base+offset
cs,Technion
4Arrays+lists למערך מימושים(2)
מימוש באמצעות מספר אזורים בזיכרון: לכל אזור גודל . nקבוע
base
k blocks
n
n
n
.k=m/n יש לבחור mכדי לממש מערך בגודל
k( בגודל baseנקצה מערך עזר )
base[ i/n ] + i נמצא בכתובת A[i] האיבר %n .
.O(1) :זמן חישוב הכתובת
n=6 דוגמא:
היא:A[16] של הכתובת
base[ 16/6 ] + 16%6 = base[2] + 4
cs,Technion
5Arrays+lists
- ממדי דו מערך
שורה - A[i]כל באורך ממדי חד מערך .nהיאint a[m][n]
A0,0 A0,1 A0,n-1
A1,0 A1,1 A1,n-1
Am-1,0 Am-1,1 Am-1,n-1
v v v
והמימוש הוא באזור זיכרון רצוף. A[0][0] היא הכתובת של baseנניח ש-
base + in היא A[i]הכתובת של שורה
base + in + j היא A[i][j]הכתובת של איבר
6Arrays+lists
- ממדי רב (1 )מערךמחושבת, כפי שראינו, A[i2][i1] הכתובת של איבר int A[n2][n1] במערך דו-ממדי:
base + i2n1 + i1 ע"י הנוסחה:מחושבת ע"י A[i3][i2][i1] הכתובת של איבר int A[n3][n2][n1] במערך תלת-ממדי:
base + i3n2 n1 + i2n1 + i1 הנוסחה:
i3
i1 n1
i2
n2
0
1
2
i3n2 n1 + i2n1 + i1
גודלמישור
אורךשורה
הוא המקום הראשוןC( a[0]) החישוב מניח קונוונצית ציינים ב-הערה:
7Arrays+lists
- ממדי רב (2 )מערך
int A[nd]…[n3][n2][n1] -ממדי:dבמערך
מחושבת ע"י הנוסחה: A[id]…[i3][i2][i1] הכתובת של
base + idnd-1 … n1 + id-1 nd-2
… n1 +…+ i1
1
11
kd
kk ni
base
)(כמה פעולות במקרה הגרוע? 2dO
)(dO
=base + ((… ((idnd-1+id-1)nd-2 + id-2)nd-3 + … + i3 ) n2+i2)n1 + i1
אבל אפשר לבטא את הכתובת באופן אלטרנטיבי:
כמה פעולות במקרה הגרוע?
8Arrays+lists
- ממדי רב (3 ) מערךהנוסחה לחישוב הכתובת במערך רב ממדי דומה לכלל הורנר לחישוב ערך
פולינום:
p(x0) = akxk + ak-1xk-1 + …+ a1x + a0 = (…(akx + ak-1)x +…+ a1)x+a0
; x: p=a[k] התוכנית הבאה מחשבת את ערך הפולינום בנקודה
for (j=k-1; j>=0; j--)
p = px + a[j]
A[id]…[i3][i2][i1] באופן אנלוגי, התוכנית הבאה מחשבת את הכתובת של base + ((… ((idnd-1+id-1)nd-2 + id-2)nd-3 + … + i3 ) הנתונה ע"י:
n2+i2)n1 + i1
addr=i[d];
for (j=d-1; j>=1; j--)
addr = addr*n[j] + i[j];
addr= base + addr;
9Arrays+lists
- ממדי רב מערך סריקת
.תלוי בסדר הסריקה A[nd]…[n3][n2][n1]זמן סריקת כל איברי מערך
. במימוש לוקליות של גישה לזיכרוןסריקה לפי סדר האחסון מהירה יותר בגלל שהצגנו, סריקה כאשר האינדקסים הנמוכים נסרקים ראשונים מהירה יותר
הוא בקבוע מסריקה בה האינדקסים הגבוהים נסרקים ראשונים. השיפור הם קבועים(ni )בהנחה ש-Oבלבד ואינו מתבטא בסימון
n1
n2
cs,Technion
10Arrays+lists
מערך איתחול
? n: כמה עולה לאתחל מערך באורך שאלה
O(n) איתחול נאיבי – תשובה:
נתאר מבנה נתונים לאיתחול מערך בזמן קבוע!
לא באמת נאתחל את המערך. נשתמש בזיכרון נוסף לציין האם כבר הרעיון:
נכתב ערך בתא במערך
11Arrays+lists נסיון לפתרון
המציינים
המוגדרים ערכים
A C
333
7
222
111
3
5
5
4
3
2
1
0 4
1
0
123
643
453
0
1
2
3
4
5
top
מציינים מוגדרים
זבל
יציין כמה איברים במערך "נכתבו" :topנשתמש במשתנה עזר
מאחסן את האינדקס ,i < top C[i]: לכל Cנשתמש גם במערך עזר
שאותו כבר "כתבנו" (i+1( של האיבר ה-)A)ב-
cs,Technion
12Arrays+lists
בזמן איתחול )O)1מערךדוגמא:
V[0]=5, V[1]=3, V[4]=7בדוגמא זו:
V המציינים מצביעים
המוגדרים לאזור הבטוח ערכים
A B C
212
131
111
222
7
333
0
1
2
3
4
5
131
224
554
675
0
234
0
1
2
3
4
5
4
177
101
123
643
453
0
1
2
3
4
5
מציינים מוגדרים
top
234זבל
0
675
554
1
131
333
7
222
111
3
212
toptop
333
7
222
111
3
5
234
0
675
554
1
2 4
1
101
123
643
453
4
1
0
123
643
453
!)O)1לא כמה "יעלה" זמן גישה?
13Arrays+lists זבל לאיתור הקודint is_garbage(int i){
return !(( B[i] < top && (B[i] >= 0) && C[B[i]] = = i))} ;
V המציינים מצביעים
המוגדרים לאזור הבטוח ערכים
A B C
333
7
222
111
3
5
5
4
3
2
1
0 131
224
554
675
0
234
0
1
2
3
4
5
4
1
0
123
643
453
0
1
2
3
4
5
top
מציינים מוגדרים
זבל234
0
675
554
1
131
234
0
2
554
1
2
C[B[4]] = = 4דוגמא לאיבר שהוכנס למבנה:
C[B[3]]= = 0 וכן C[B[5]] > topדוגמאות לזבל:
14Arrays+lists לפעולות המערך הקוד
if (is_garbage(i))
return constant;
else
return A[i];
if (is_garbage(i)) }
C[top] = i ;
B[i] = top ;
top = top +1;{
A[i]= e;
top = 0;
constant = const;:init(V,const)אתחל
:get(V,i)אחזר
:store(V,i,e)שמור
A ניתן להשתמש במערך ( top > n): ברגע שהמערך מתמלאהערה.Aבלבד כיוון שאין, ויותר לא יהיה, זבל ב-
15Arrays+lists
סימטריות מטריצות ייצוג. A[i,j]=A[j,i] דו-ממדי המקיים Aמטריצה סימטרית היא מערך
0 1 2 3 n
0 1
1 2 3
2 4 5 6
3 7 8 9 10
n … … …
אוסף וקטורים המאוחסנים במערך רציף יחיד:הייצוג:
1 2 3 4 5 6 7 8 9 10
i = i(i+1)/2+…+1+2 נשתמש בנוסחה: ?A[i,j] מהי הכתובת של איבר
Addr(i,j)= { Base + i ( i+1 )/2 + j if i j
Addr(j,i) Otherwise
חצי תחתון
חצי עליון
16Arrays+lists
דלילות מטריצות ייצוגמטריצה דלילה היא מערך דו-ממדי עבורו "רוב מוחלט" של
כלשהו(.מהו רוב מוחלט ? cהאיברים שווה לאפס )או לקבוע
0 1 2 3 4 5 6 7
0 3 1
1 5
2 4
3
4 2 7 8
מקיימת שמספר האיברים השונים ... M1...Mn: אם סדרת מטריצות הגדרה אסימפטוטית הוא מספר המקומות המקסימלי m(n) קטן( כאשר o )o(m(n)) הוא מסדר גודל של cמקבוע
: מטריצות אלכסוניות. במטריצות דוגמא אז זוהי סדרה של מטריצות דלילות. Mnבמטריצה .o(n2) הוא c מספר האיברים השונים מקבוע nnריבועיות דלילות מגודל
28 מתוך 7בדוגמא זו איברים שונים מהקבוע.
מסודרות בסדר לקסיקוגרפי.( i,j,Aij) שלשות"רשימת": ייצוג
(4,5,8(, )4,4,7(, )4,1,2(, )2,3,4(, )1,1,5(, )0,5,1(, )0,2,3): דוגמא
17Arrays+lists
הייצוג של ויתרונות חסרונות מסודרות בסדר לקסיקוגרפי.( i,j,Aij): רשימת שלשותהייצוג
.O(1): אין גישה אקראית לפי מציין בזמן חסרון עקרי
: חוסך בזיכרון עבור מטריצות דלילות.יתרונות
מאיץ פעולות חיבור וכפל של מטריצות דלילות.
.O(n2) לוקח בייצוג רגיל זמן n X n בגודל חיבור מטריצות
בשניה. k במטריצה אחת ו-c איברים שונים מהקבוע mנניח כעת שיש חיבור שתי המטריצות נעשה ע"י מיזוג שתי הרשימות המייצגות את
.O(m+k)המטריצות נ"ל. זמן המיזוג הוא אורכן הכולל של הרשימות כלומר .o(n2)כלומר עבור מטריצות ריבועיות דלילות זמן החיבור הוא
בייצוג זה לוקח זמןדלילות מטריצות ריבועיות כפל: הראו שתרגיל ממבחןo(n3) במקום O(n3) לשם כך נדרש מיון לפי עמודות של מטריצה .B.
cs,Technion
18Arrays+lists
מטריצות לחיבור C=A+B תוכניתtypedef struct NODE{
int row, col;
float val;
{
NODE A[mA+1], B[mB+1], C[mA+mB+1];
int lex(NODE a, NODE b);
/* lexicographically compares a and b;
Returns: -1 if (a.row,a.col) < (b.row,b.col)
0 if (a.row,a.col) = (b.row,b.col)
1 if (a.row,a.col) > (b.row,b.col) */
void ADD(NODE *A, NODE *B, NODE *C, int *mC){int i=0, j=0, *mc=0;A[mA]=B[mB]=}+,+, 0{;while (i < mA || j < mB)} switch lex(A[i],B[j])}
case –1: C[*mC++] = A[i++]; break;case 1: C[*mC++] = B[j++]; break;case 0: C[*mC].row = A[i].row;
C[*mC].col = A[i].col; C[*mC].val = A[i++].val + B[j++].val; if (C[*mC].val 0) *mC++;
{{{
cs,Technion
19Arrays+lists
מקושרות רשימות
( find, insert, deleteנזכר כעת כיצד מתבצע חיפוש, הכנסה, והוצאה )ברשימות מקושרות ונגדיר וריאציות עליהן.
למערך בהשוואה :יתרונות
7head 2 6 5
.1. דינמית זיכרון הקצאת מאפשר
זיכרון 2. מקום להקצות צורך איןרצוף.
רשימה 3. מתוך איבר להוציא ניתן " כמו " חור להשאיר בלי מקושרת
כל את לסרוק ניתן ולכן במערך. ליניארי בזמן האיברים
למערך בהשוואה :חסרונות
בזמן 1. אינדקס לפי גישה .O(1)אין
cs,Technion
20Arrays+lists מקושרת ברשימה חיפוש
איתחול פעולתinit(head):
O(n)חיפוש איבר בזמן במקרה הגרוע.
NODE * find (DATA_TYPE x, NODE *head){
NODE *t;
for (t = head; t != NULL && t -> info != x;
t = t -> next );
return t;
}
פעולת חיפוש find(x,head):
void init (NODE *head){
(* head) = NULL;
}
7head 2 5
t
cs,Technion
21Arrays+lists לרשימה איבר הכנסתמקושרת
}insert(t,x):int insert ( NODE *t, DATA_TYPE x)פעולת
NODE *p;
if (t == NULL) return 0;
p = (NODE *) malloc (sizeof (NODE));
p -> info = x;
p -> next = t -> next ;
t -> next = p ;
return 1;
}
7head 2
6
5
t
O(1)הכנסת איבר בזמן כאשר ידוע מקום ההכנסה.
.insert(t,6)דוגמא:
מצביע לצומת tהפרמטר שאחריו מוסיפים צומת חדש.
cs,Technion
22Arrays+lists מקושרת מרשימה איבר הוצאת
}delete(t):delete ( NODE *t)פעולת
NODE * temp ;
temp = t next; /* מצביע לצומת שמורידים*/
t next = temp next ;
free (temp) ;
} O(1)הוצאת איבר בזמן
כאשר ידוע מקום ההוצאה.
7head 2
6
5
t
temp
מצביע לצומת tהפרמטר שלפני הצומת שמוציאים.
cs,Technion
23Arrays+lists רשימה מראש איבר הוצאתמקושרת
p_head
:delete_first(r)פעולת int delete_first ( NODE **p_head){
NODE * temp ;
if (*p_head = = NULL) return 0 ;
temp = *p_head;
*p_head = temp next ;
free (temp) ;
return 1; /* success code */
}
7head 2 5
? תכנות זה מסורבל. מהו הפתרון לכך
cs,Technion
24Arrays+lists כותרת עם רשימות: . " חוסכת " זו תוספת הרשימה בתחילת ריק איבר מוסיפים
ריקות • ברשימות מיוחד טיפול•. הראשון הצומת לפני הכנסה בזמן מיוחד טיפול
head 2 5
איברים שתי בת רשימה זה בייצוג: כך ממומשת
ממומשת ריקה ורשימהכך:
head
5head
1
2
זהה ראשון איבר לפני הכנסה: כלשהו איבר לפני להכנסה
cs,Technion
25Arrays+lists מעגליות רשימות
7
rear
2
6
5
:יתרונותאיבר • לכל איבר מכל להגיע אפשרבזמן • מעגליות רשימות לשרשר ניתן
קבוע.
9
temp
rear1
2 5
9 7
3 4
6 8
rear2
cs,Technion
26Arrays+lists - כיוונית דו מקושרת רשימה
8 952
t
)ולא רק את אליוt : מאפשר להוציא איבר בהינתן מצביע יתרוןהאיבר שאחריו(.
t next prev = t prev;
t prev next = t next;
8 952
t
cs,Technion
27Arrays+lists " טריקית " הוצאה
גם מרשימה חד-כוונית ?t האם ניתן להוציא איבר אליו מצביע
2head 5 9
t
8
מצביע אליו t לתא ש- tפשוט נעתיק את האינפורמציה בתא העוקב ל-ונוציא את התא העוקב.
2head 8 9
t
8
מהן החסרונות של שיטה זו ?
צומת יכול להכיל הרבה אינפורמציה ולכן העתקה עלולה להיות פעולה ארוכה.•
יתכן וישנם מצביעים נוספים לתא שהוצא ואין אפשרות לעדכן מצביעים אלה.•
cs,Technion
28Arrays+lists פולינומים ייצוג
אחד . נעלםדוגמא:
וכן גדול והנמוכה הגבוהה החזקה בין ההפרש כאשר יעיל זה מימוש . מתאפסים הביניים חזקות של מקדמים הרבה
מקדם
24.5 00.190.3
חזקה
1.05.43.0 29 xx
נעלמים :שני )52()13()714(דוגמא. 229 yxyxy
2 0 9
1 2 05
2 3 0 1
1 14 0 7
cs,Technion
29Arrays+lists דלילות מטריצות ייצוג
column
row value next
down
:מבנה צומת
typedef struct node{
float value ;
struct node*next, *down ;
int row, column ;
}NODE;
0
1
2
3
3210
4
4
cs,Technion
30Arrays+lists דלילות מטריצות כפל. C = ABכפל מטריצות
התוכנית מחשבת את האיבר Cij.
#define N_row 20
#define N_col 20
NODE *row_header[N_row],
*col_header[N_col];
*/Compute the value of c[i][j]/*
double mult_row_col(int i, int j){
double c = 0;
NODE *r = row_header[i], *k = col_header[j];
while (r != NULL && k != NULL)}
if (r column < k row) r = r next ;
else (r column > k row) k = k down ;
else /* r->column ==k->row */
c + = r value * k value ;
r = r next ; k = k down ; {return c;
}