הרצאה 10: אלגוריתמי מיון רקורסיביים Merge sort ו-Quick sort

Slides:



Advertisements
מצגות קשורות
אוגרים ומונים – Registers & Counters
Advertisements

תכנות בשפת C תרגול 11 - קבצים.
הרצאה 02 סוגי משתנים קרן כליף.
ניווט רובוט מסוג ROOMBA במרחב ממופה
ייצוגים שונים של פונקציה
יצירת מקרו הפעלת מקרו יצירת לחצן / פקד דוגמה מסכמת
הרצאה 12: מיזוג, מיון ושימושים לפעולות על קבוצות - המשך
מבוא לתכנות ב-JAVA מעבדה 1
טיפים מנצחים: לחפש ולמצוא במהירות ובדיוק
בקרת מודל אורכי מפושט של F-14, בעזרת VSC גל מזרחי תם שפירא.
תרגול 11: רקורסיה ופיתוח טלסקופי
נערך ע"י אריק הוד, הגימנסיה העברית הרצליה
מיונים (SORTS) שמושים ביישומים רבים
ייצוג קבוצות מתוחכם עצי חיפוש בינאריים BINARY SEARCH TREES
מבוא למדעי המחשב מ' - תירגול 9
יצוג קבוצות מתוחכם עצי חיפוש בינאריים BINARY SEARCH TREES
תירגול 10: מבנים (structs) וקבצים
Marina Kogan Sadetsky –
רמי כהן, מדעי המחשב, הטכניוןכל הזכויות שמורות ©
Jump tables, review questions
הרצאה 3: משפטים, תנאים ולולאות
מבוא למדעי המחשב הרצאה מספר 12: רקורסיה
תכנות בשפת C תרגול 11 רשימות מקושרות מבנים
פעולות אריתמטיות קרן כליף.
Computer Programming תרגול 1 Summer 2016
תירגול 11: מיונים וחיפוש בינארי

תכנות בשפת C תרגול 8 רקורסיה
Engineering Programming A
תירגול 8:מצביעים והקצאה דינאמית
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
מבוא למדעי המחשב הרצאה 9: רקורסיה
תרגול 6: פונקציות, סוגי משתנים, top-down design
S. Even, "Graph Algorithms", Computer Science Press, 1979
תירגול 2: מבוא לתיכנות ב-C
Carry Save Adder (CSA).
כל הזכויות שמורות לגבריאל אנקרי © 2017
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
יישומון הר לעמק 2019 הוראות הפעלה.
חניון עין-זיון הצבת לוח זיכרון לתיאור לחימת גדס"ר 134
מבוא לתכנות למערכות מידע
מבנה מחשבים ספרתיים זכרון וירטואלי מבוסס על תרגול של מורן גביש
אלגוריתמי מיון רקורסיביים
אנליטית זוית בין שני ישרים הוכחה ~> דוגמא ~> סיכום!! ^_^
כל הזכויות שמורות לגבריאל אנקרי © 2017
תרגול 13 : חזרה נכתב על-ידי לימור ליבוביץ נערך ע"י ישראל גוטר
Marina Kogan Sadetsky –
מת"מ מעבדה 7-8 רשימות.
Solving Simultaneous Linear Equations Using GPU
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
צמצום בעזרת מפת קרנו.
מבוא לתכנות ב- JAVA מעבדה 4
מבוא למדעי המחשב סמסטר ב' – 2008 מרצה: יעל סיגל מתרגל: ענבל בודובסקי.
Ci,j=Σκ Ai,κxBκ,j מכפלת מטריצות מכפלת מטריצות ב- O(n3)
Introduction to Programming in C
תרגול 12: backtracking.
מצביעים Pointers – המשך...
שרטוט ידני - חלק 1.
Data Structures, CS, TAU, Perfect Hashing
תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה
חקרנות מתמטית: הקשר בין שטחים והיקפים - האומנם?
עקרונות תכנות מונחה עצמים תרגול 9:C++ - תרגילים
רקורסיה ופתרונות רקורסיביים
שוק העבודה בישראל פרופ' ערן ישיב
Java Programming רשימות מקושרות - המשך
Pre-Medical Studies לימודי קדם רפואה B.Sc..
Engineering Programming A
רשימות מקושרות עבודה עם קבצים דוגמה
תמליל מצגת:

הרצאה 10: אלגוריתמי מיון רקורסיביים Merge sort ו-Quick sort מבוא למדעי המחשב הרצאה 10: אלגוריתמי מיון רקורסיביים Merge sort ו-Quick sort מבוסס על שקפים שנערכו ע"י שי ארצי, גיתית רוקנשטיין, איתן אביאור, וסאהר אסמיר, מיכאל אלעד‘, רון קימל ודן רביב. עדכון אחרון סמסטר חורף 2013.

מבוא למדעי המחשב. כל הזכויות שמורות © תוכנייה Merge-Sort רקורסיבי הדגמה מימוש ניתוח סיבוכיות Quick-sort דוגמא מבחינה מבוא למדעי המחשב. כל הזכויות שמורות ©

מיון באמצעות מיזוג – אלגוריתם רקורסיבי תזכורת: מיון מערך a[] באורך n ב-Merge-Sort נעשית ע"י: מיון תת-מערך שמאלי של a[] באורך n/2. מיון תת-מערך ימני של a[] באורך n - n/2. מיזוג שני תתי המערך הממוינים. בסיס הרקורסיה: מערך באורך 1 הינו ממוין ממילא. התיאור הנ"ל מתאים מאוד למימוש רקורסיבי. הערה: אלגוריתם ה- Merge-Sort נדרש להקצאת זיכרון של מערך עזר לביצוע המיזוגים. רצוי לטפל בהקצאה זו מחוץ לרקורסיה. מבוא למדעי המחשב. כל הזכויות שמורות ©

Merge-Sort רקורסיבי– מימוש void merge_sort(int a[], int n) { int *tmp_array = malloc(sizeof(int) * n); internal_msort(a, n, tmp_array); free(tmp_array); } void internal_msort(int a[], int n, int helper_array[]) int left = n / 2, right = n – left; if (n < 2) return; internal_msort(a, left, helper_array); internal_msort(a + left, right, helper_array); merge(a, left, a + left, right, helper_array); memcpy(a, helper_array, n * sizeof(int)); מבוא למדעי המחשב. כל הזכויות שמורות ©

Merge-Sort רקורסיבי– הסברים הפונקציה לעיל ממיינת גם כאשר n אינו חזקה של 2. המשתנים right, left מכילים את גודל תתי-המערך הימני והשמאלי. הרשימות שיש למזג יושבות במערך שבו צריכה לשבת התוצאה. כדי לא למחוק איברים שלא טופלו, ממזגים את המערך השמאלי והמערך הימני לתוך מערך זמני. בשלב הבא מעתיקים את המערך הזמני בחזרה לתוך המערך המקורי. כיצד נשנה את הקוד כך שישתמש במערך זמני שגודלו n/2 ? שמאלי ימני זמני מבוא למדעי המחשב. כל הזכויות שמורות ©

Merge-Sort רקורסיבי– סיבוכיות זמן סיבוכיות הזמן היא כיוון שמתבצעים אותם מיזוגים כמו באלגוריתם האיטרטיבי שראינו. דרך נוספת לחישוב מספר הפעולות ברקורסיה: void internal_msort(int a[], int n, int helper_array[]) { int left = n / 2, right = n – left; if (n < 2) return; internal_msort(a, left, helper_array); internal_msort(a + left, right, helper_array); merge(a, left, a + left, right, helper_array); memcpy(a, helper_array, n * sizeof(int)); } מבוא למדעי המחשב. כל הזכויות שמורות ©

Merge-Sort רקורסיבי– סיבוכיות מקום עומק הרקורסיה, כלומר מספר הקריאות הרקורסיביות של internal_msort() שפתוחות בו-זמנית, הינו לכל היותר log2 n. כל אחת מהן צורכת Θ(1) זיכרון עבור המשתנים. הפונקציה merge_sort() מקצה זיכרון נוסף בגודל Θ(n). סיבוכיות המקום הכוללת של merge_sort() במימוש רקורסיבי הינה: Θ(n+log n)= Θ(n) מבוא למדעי המחשב. כל הזכויות שמורות ©

מבוא למדעי המחשב. כל הזכויות שמורות © תוכנייה Merge-Sort רקורסיבי הדגמה מימוש ניתוח סיבוכיות Quick-Sort דוגמא מבחינה מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – מיון רקורסיבי יעיל נתון מערך a[] של מספרים שלמים בגודל n. נסמן p=a[0] איבר הציר – pivot. שלב החלוקה – partition. נארגן את איברי המערך (מלבד ה-pivot) בשני חלקים: נחליף בין ה-pivot לאיבר במקום ה-t: 3 2 5 4 1 6 7 0 1 t t+1 n-1 3 2 1 5 4 6 7 קטנים מה- pivot גדולים/שווים ל-pivot 5 2 3 4 7 6 1 קטנים מה- pivot t גדולים/שווים ל-pivot מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – מיון רקורסיבי יעיל (המשך) בסוף התהליך שתואר קודם: האיברים a[0]…a[t-1] כולם קטנים מהערך של ה-pivot. האיבר pivot נמצא במקום הסופי המיועד לו a[t]. האיברים a[t+1]…a[n-1] כולם גדולים/שווים לערך של pivot. כל אחד מהחלקים (ימין ושמאל) אינו בהכרח ממוין. אין איבר שנמצא בחלק "הלא נכון" – כלומר אין איבר שיעבור בסוף מהחלק הימני לשמאלי וההיפך. צעד הרקורסיה: נמיין רקורסיבית את החלק הימני a[0]…a[t-1] ואת החלק השמאלי a[t+1]…a[n-1]. בסיס הרקורסיה: מערך בגודל 1 – בהכרח ממוין. החוכמה העיקרית טמונה במימוש יעיל של שלב החלוקה (partition). מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – הצעה לביצוע החלוקה סורקים את המערך בכיוון ימין (b) ובכיוון שמאל (t). כל עוד (t>=b) ו- (a[t]>=p) מקטינים את t. כל עוד (b<=t) ו- (a[b]<p) מגדילים את b. אם במהלך הסריקה מגיעים למצב בו (p<=a[b])&&(p>a[t]), מבצעים החלפה וחוזרים ל-1. הסריקה נפסקת כאשר (t<b). במקרים אלו החלוקה הושלמה. 1 2 n-1 p b t 1 2 n-1 p b t מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – דוגמה לביצוע החלוקה 7 > 3? 2 < 3? 5 > 3 && 1 < 3? 0 > 3? 4 < 3? 4 > 3 && 0 < 3? 6 > 3? 5 < 3? 1 > 3? 3 2 5 4 1 6 7 b t מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – מימוש void quick_sort(int a[], int n) { int p, b = 1, t = n - 1; if (n < 2) return; swap(&a[0], &a[n/2]); p = a[0]; while(b <= t) { while(t >= b && a[t] >= p ) t--; while(b <= t && a[b] < p) b++; if ( b < t) swap(&a[b++], &a[t--]); } swap(&a[0], &a[t]); quick_sort(a, t); quick_sort(a + t + 1, n – t - 1); במימוש חכם של quick-sort, איבר הציר נבחר באקראי מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – ניתוח סיבוכיות סיבוכיות שלב החלוקה של מערך בגודל n היא Θ(n). ערכי ה-pivot קובעים את זמן הריצה ואת עומק הרקורסיה. 1 2 3 4 5 log2 n "שכבות" ברקורסיה: סיבוכיות הפעולות בכל שכבה הינה O(n). לכן סיבוכיות הזמן הכוללת: Θ(n log n) זהו המקרה הטוב ביותר. n "שכבות" ברקורסיה: סיבוכיות זמן כוללת n+(n-1)+…+1=O(n2) זהו המקרה הגרוע ביותר. מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – ניתוח סיבוכיות (המשך) נהוג לבחור את איבר הציר באקראי (ואז להחליפו עם a[0]). בקוד שלהלן מחליפים את a[n/2] עם a[0]. סיבוכיות הזמן של אלגוריתם Quick-Sort הינה Θ(n2). אף על פי כן, האלגוריתם נחשב יעיל כיוון ש"בממוצע" איברי הציר "טובים" והמיון מהיר: O(n log n) פעולות. כאשר איברי הציר טובים, סיבוכיות המקום של אלגוריתם quick sort הינה O(log n). במקרה הגרוע סיבוכיות המקום היא O(n). הזיכרון הנוסף משמש עבור הקריאות הרקורסיביות. אין צורך להקצות מערך עזר. קיימת פונקצית ספריה של C הנקראת qsort() ומממשת מיון זה. מבוא למדעי המחשב. כל הזכויות שמורות ©

מבוא למדעי המחשב. כל הזכויות שמורות © תוכנייה Merge-Sort רקורסיבי הדגמה מימוש ניתוח סיבוכיות Quick-Sort דוגמא מבחינה מבוא למדעי המחשב. כל הזכויות שמורות ©

מבוא למדעי המחשב. כל הזכויות שמורות © דוגמה ממבחן נתון מערך a של שלמים שיתכנו בו חזרות (ערכים זהים). כתבו פונקציה partial_sort() המקבלת כפרמטרים את כתובת המערך a הנ''ל ואת גודלו n ומסדרת את איבריו כך שכל האיברים השווים לערך הקטן ביותר במערך יופיעו בתחילתו (אין מגבלה על הסדר היחסי בין שאר האיברים). על הפונקציה להחזיר את מספר האיברים במערך השווים לערך הקטן ביותר. דרישות סיבוכיות: זמן Θ(n) ומקום נוסף Θ(1). מותר לבצע שינויים במערך a אך ורק ע''י שימוש בפונקציה swap(). דוגמא: 2 3 7 4 5 2 3 7 4 5 מבוא למדעי המחשב. כל הזכויות שמורות ©

Quick-Sort – דוגמה לביצוע החלוקה הפתרון שנציע מושתת על תהליך ההחלפה ב- Quick-Sort עם pivot שאינו אלא האיבר המינימאלי. לדוגמה, עבור הסדרה נתחיל בחיפוש הערך המינימאלי – זהו min_val=2. נאתחל מצביעים לתחילת המערך ולסופו, ונריצם זה מול זה עם החלפות לפי הצורך, לפי התהליך הבא: עולים ב-b כל עוד זה הערך המינימאלי. יורדים ב-t עד מציאת ערך מינימאלי. מחליפים בין השניים . עצירה כאשר t<b. 2 3 4 7 5 2 3 2 7 4 5 2 b t מבוא למדעי המחשב. כל הזכויות שמורות ©

מבוא למדעי המחשב. כל הזכויות שמורות © דוגמה ממבחן – פתרון int partial_sort (int a[], int n) { int min_val; min_val=a[0]; for(i=1; i<n; i++) // Phase 1 – finding mimimum value if(a[i]<min_val) min_val=a[i]; int i, b = 0, t = n-1; while(b<=t) { // Phase 2 – swapping locations to order while (b<n && a[b]==min_val) b++; while (a[t]>min_val) t--; if(b<t) swap(&a[b++], &a[t--]); } return (t+1); מבוא למדעי המחשב. כל הזכויות שמורות ©

מבוא למדעי המחשב. כל הזכויות שמורות © דוגמה ממבחן (המשך) נתון מערך a של שלמים בגודל n, וידוע שבין n איברי המערך יש רק k ערכים שונים זה מזה (כלומר ישנם איברים החוזרים על עצמם במערך). כתבו פונקציה רקורסיבית sort() המקבלת את המערך a ואת גודלו n וממיינת את המערך. לפונקציה sort() מותר להשתמש בפונקציה partial_sort() מהסעיף הקודם גם אם לא עניתם על סעיף א'. דרישות סיבוכיות: זמן Θ(kn) ומקום נוסף Θ(k). פתרון: נשתמש ב- partial_sort() שוב ושוב, כל פעם לאתר את הערך המינימאלי במערך,ואז לקבצם בתחתיתו. אנו נתייחס למערך הולך וקצר, עם נקודת התחלה שמתייחסת לאיבר הראשון השונה מהמינימום. מבוא למדעי המחשב. כל הזכויות שמורות ©

מבוא למדעי המחשב. כל הזכויות שמורות © דוגמה ממבחן (המשך) דוגמה: 2 3 4 7 5 2 3 4 7 5 2 3 4 7 5 2 3 4 7 5 2 3 4 7 5 void sort (int a[], int n) { int m; if (n<=1) return; m = partial_sort(a,n); sort(a+m, n-m); } דרישות הסיבוכיות: זמן Θ(kn) ומקום נוסף Θ(k) (בשל המחסנית ברקורסיה) מתקבלות כנדרש. מבוא למדעי המחשב. כל הזכויות שמורות ©