המצגת נטענת. אנא המתן

המצגת נטענת. אנא המתן

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

מצגות קשורות


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

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

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

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

4 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)); מבוא למדעי המחשב. כל הזכויות שמורות ©

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

6 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)); } מבוא למדעי המחשב. כל הזכויות שמורות ©

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

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

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

10 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). מבוא למדעי המחשב. כל הזכויות שמורות ©

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

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

13 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, איבר הציר נבחר באקראי מבוא למדעי המחשב. כל הזכויות שמורות ©

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

15 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() ומממשת מיון זה. מבוא למדעי המחשב. כל הזכויות שמורות ©

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

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

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

19 מבוא למדעי המחשב. כל הזכויות שמורות ©
דוגמה ממבחן – פתרון 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); מבוא למדעי המחשב. כל הזכויות שמורות ©

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

21 מבוא למדעי המחשב. כל הזכויות שמורות ©
דוגמה ממבחן (המשך) דוגמה: 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) (בשל המחסנית ברקורסיה) מתקבלות כנדרש. מבוא למדעי המחשב. כל הזכויות שמורות ©


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

מצגות קשורות


מודעות Google