מערכים, מטריצות דלילות, ורשימות מקושרות

Post on 11-Jan-2016

138 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

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 Presentation

TRANSCRIPT

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;

}

top related