Download presentation
Presentation is loading. Please wait.
1
תרגול 10 ערימות מיון מהיר
2
Heaps
3
Heaps Heap Maximum-Heap Minimum-Heap Heap-Array
A binary heap can be considered as a complete binary tree, (the last level is full from the left to a certain point). Maximum-Heap For each node x, x ≥ left(x) and x ≥ right(x) The root in a Maximum-Heap is the maximal element in the heap Minimum-Heap For each node x, x ≤ left(x) and x ≤ right(x) The root in a Minimum-Heap is the minimal element in the heap Heap-Array A heap can be represented using an array: A[1] - the root of the heap (not A[0]) length[A] - number of elements in the array heap-size[A] - number of elements in the heap represented by the array A For each index i : Parent(i) = 𝑖 2 Left(i) = 2i Right(i) = 2i+1
4
Heaps Actions on Heaps Insert ~ 𝑂 log 𝑛 Max ~ 𝑂 1
Extract-Max ~ 𝑂 log 𝑛 Build-Heap ~ 𝑂 𝑛 Down-Heapify(H, i) – same as MaxHeapify seen in class but starting in the node in index i ~ 𝑂 log 𝑛 Up-Heapify(H, i) – Fixing the heap going from node in index i to the root as in Insert() ~ 𝑂 log 𝑛 הרעיון של MaxHeapify – לדאוג שהערימה תשמור על מבנה תקין (לוודא ש-A[i] גדול מילדיו) המימוש – למצוא את הבן הגדול של A[i] ולבצע ביניהם החלפה
5
Heaps דוגמה: הוסיפו את 9 מוסיפים את הערך 9 כעלה
דוגמה: הוסיפו את 9 מוסיפים את הערך 9 כעלה מבצעים Up-Heapify לתיקון הערימה 7 11 13 21 12 17 20 34 22 51 14 41 9 Heap_size 7 11 13 21 12 17 20 קטן מאביו – מבצעים החלפה 34 22 51 14 41 9
6
Heaps דוגמה: הוסיפו את 9 מוסיפים את הערך 9 כעלה
דוגמה: הוסיפו את 9 מוסיפים את הערך 9 כעלה מבצעים Up-Heapify לתיקון הערימה 7 11 13 21 12 9 20 34 22 51 14 41 17 Heap_size 7 גדול מאביו – מסיימים 11 13 קטן מאביו – מבצעים החלפה 21 12 9 20 34 22 51 14 41 17
7
Heaps דוגמה: כעת בצעו Extract-min Key = 7
דוגמה: כעת בצעו Extract-min מוציאים את השורש (ושומרים את ערכו) מעבירים לשורש את העלה האחרון מבצעים Down-Heapify מהשורש לתיקון הערימה 7 11 9 21 12 13 20 34 22 51 14 41 17 17 Heap_size Key = 7 7 11 9 21 12 13 20 34 22 51 14 41 17
8
Heaps דוגמה: כעת בצעו Extract-min Key = 7
דוגמה: כעת בצעו Extract-min מוציאים את השורש (ושומרים את ערכו) מעבירים לשורש את העלה האחרון מבצעים Down-Heapify מהשורש לתיקון הערימה 17 11 9 21 12 13 20 34 22 51 14 41 17 Heap_size גדול מבנו הקטן – מבצעים החלפה Key = 7 17 11 9 21 12 13 20 34 22 51 14 41
9
Heaps דוגמה: כעת בצעו Extract-min Key = 7
דוגמה: כעת בצעו Extract-min מוציאים את השורש (ושומרים את ערכו) מעבירים לשורש את העלה האחרון מבצעים Down-Heapify מהשורש לתיקון הערימה מחזירים את הערך שנשמר 9 11 17 21 12 13 20 34 22 51 14 41 17 Heap_size Key = 7 9 11 גדול מבנו הקטן – מבצעים החלפה 17 קטן מבנו הקטן – מסיימים 21 12 13 20 34 22 51 14 41
10
שאלה 1 בהינתן ערימת מקסימום H
תשובה: זה לוקח O(1) למצוא את 3 המפתחות הגדולים ב-H. 3 המפתחות הגדולים ב-H הם: השורש הבן המקסימלי של השורש, y המפתח הגדול מבין אחיו של y והבן המקסימלי של y
11
שאלה 1 בהינתן ערימת מקסימום H
מהי סיבוכיות זמן הריצה של מציאת C המפתחות הגדולים ב-H? (C קבוע) תשובה: מציאת C המפתחות הגדולים ביותר ב-H מתבצעת בצורה דומה: המפתח ה-i בגודלו הוא אחד מתוך i מפתחות שונים לכל היותר, הבנים של i-1 המפתחות הגדולים ביותר שלא נלקחו עד כה, לכן ניתן למצוא אותו ב-O(i). ⇐ זמן מציאת C המפתחות הגדולים ביותר הוא O(C2)=O(1)
12
שאלה 1 בהינתן ערימת מקסימום H
מהי סיבוכיות זמן הריצה של מציאת C המפתחות הגדולים ב-H? (C אינו קבוע) תשובה: אם C אינו קבוע, עלינו להיות יעילים יותר. נשתמש בערימת מקסימום חדשה בצורה הבאה: לכל מפתח מקסימלי שנוציא, נכניס את שני בניו לערימה החדשה, תוך שמירה על הצבעה הדדית. הקודקוד הראשון שיוכנס לערימה החדשה יהיה השורש. נבצע C פעמים ExtractMax() על הערימה החדשה, כך שלאחר הוצאת המפתח המקסימלי, נבצע Insert() של שני בניו מהערימה המקורית. בערימה החדשה יש לכל היותר C אלמנטים, לכן זמן הריצה יהיה O(C log(C)). *שימו לב שהערימה המקורית לא משתנה.
13
שאלה 1 הדגמה: מצאו את 5 המפתחות הקטנים ביותר בערימה בעזרת האלגוריתם
7 נכנס לערימה החדשה 7 יוצא, 11 ו-13 נכנסים 11 יוצא, 12 ו-21 נכנסים 12 יוצא, 14 ו-51 נכנסים 13 יוצא, 17 ו-20 נכנסים 14 יוצא 7 11 13 12 7 11 13 14 21 12 17 20 13 17 14 21 51 20 34 22 51 14 41 9
14
שאלה 2 נתחו את סיבוכיות זמן הריצה של מציאת i האלמנטים הקטנים ביותר בקבוצה בגדול n בשימוש בשיטות הבאות: מיון תור עדיפויות
15
שאלה 2 נתחו את סיבוכיות זמן הריצה של מציאת i האלמנטים הקטנים ביותר בקבוצה בגדול n בשימוש בשיטות הבאות: מיון: מיינו את המספרים באמצעות אלגוריתם מבוסס השוואות - 𝑂 𝑛⋅ log 𝑛 מצאו את i האלמנטים הקטנים ביותר ב-𝑂 𝑖 סה"כ: 𝑂 𝑖+𝑛⋅ log 𝑛 =𝑂 𝑛⋅ log 𝑛
16
שאלה 2 נתחו את סיבוכיות זמן הריצה של מציאת i האלמנטים הקטנים ביותר בקבוצה בגדול n בשימוש בשיטות הבאות: תור עדיפויות: בנו ערימת מינימום ב-𝑂 𝑛 בצעו ExtractMin() i פעמים ב-𝑂 𝑖⋅ log 𝑛 סה"כ: 𝑂 𝑛+𝑖⋅ log 𝑛 באמצעות שאלה 1 ניתן לצמצם את זמן הריצה ל-𝑂 𝑖⋅ log 𝑖 שימו לב ש: 𝑛+𝑖 ⋅log 𝑖 =Θ max 𝑛, 𝑖⋅ log 𝑖 וברור שמתקיים 𝑛+𝑖⋅ log 𝑛 =𝑂(𝑛⋅ log 𝑛 )
17
שאלה 3 בערימה H שמיוצגת בעזרת מערך, הציעו אלגוריתם להוצאת הערך במיקום ה-i (הניחו כי i קטן מגודל הערימה). מה זמן הריצה של האלגוריתם?
18
שאלה 3 הדגמה: בצעו Extract(H,2) 7 11 9 21 12 13 20 34 22 51 14 14
9 11 17 21 12 13 20 34 22 51 14 14 הדגמה: בצעו Extract(H,2) 7 11 9 21 12 13 20 34 22 51 14 14
19
שאלה 3 בערימה H שמיוצגת בעזרת מערך, הציעו אלגוריתם להוצאת הערך במיקום ה-i (הניחו כי i קטן מגודל הערימה). מה זמן הריצה של האלגוריתם? Solution: Extract(H, i) key H[i] H[i] H[heap_size] /*Deleting the i'th element and replacing it with the last element*/ heap_size heap_size − /*Effectively shrinking the heap*/ Down-Heapify(H, i) /*Subtree rooted in H[i] is a legal heap*/ Up-Heapify(H, i) /*Area above H[i] is a legal heap*/ return key שימו לב – גם בערימת מינימום וגם בערימת מקסימום יכול להיווצר מצב שבו נצטרך לבצע Up_Heapify או Down_Heapify מבצעים את שתיהן מכיון שאין לנו דרך לדעת לאיזה כיוון נצטרך לתקן, ומכיוון שתיקון לשני הכיוונים לא משפיע לנו על זמן הריצה.
20
שאלה 3 הדגמה: בצעו Extract(H,2) i Key = 11 key H[i]
9 11 17 21 12 13 20 34 22 51 14 14 הדגמה: בצעו Extract(H,2) key H[i] H[i] H[heap_size] heap_size -- Down-Heapify(H, i) Up-Heapify(H, i) return key Heap_size Key = 11 7 גדול מאביו – מסיימים גדול מבנו הקטן – מבצעים החלפה 11 9 קטן מבנו הקטן – מסיימים 21 12 13 20 34 22 51 14 14
21
שאלה 4 נתונות שתי ערימות מינימום, 𝐻 1 (המכילה 𝑛 1 איברים) ו- 𝐻 2 (המכילה 𝑛 2 איברים). כל איבר של 𝐻 1 קטן ממש מכל איבר של 𝐻 2 . איך ניתן למזג את שתי הערימות לערימה אחת H (המכילה 𝑛 1 + 𝑛 2 מפתחות) תו"כ שימוש ב-𝑂 𝑛 2 זמן בלבד? (הניחו כי שתי הערימות מיוצגת ע"י מערכים שגודלם גדול מ- 𝑛 1 + 𝑛 2 )
22
שאלה 4 פתרון: אם 𝑛 1 ≥ 𝑛 2 : אם 𝑛 2 > 𝑛 1 :
אם 𝑛 1 ≥ 𝑛 2 : צרף את איברי 𝐻 2 למערך של 𝐻 1 החל מהמקום ה- 𝑛 1 +1 עד המקום ה- 𝑛 1 + 𝑛 2 −1. טענה: כל האיברים של 𝐻 1 הוכנסו כעלים לערימה. הוכחה: עבור כל 𝑖∈ 𝑛 1 +1, 𝑛 1 + 𝑛 2 , האבא של 𝐴[𝑖] הוא 𝐴 𝑖 2 וכן מתקיים 𝑖 2 ≤ 𝑛 1 + 𝑛 2 2 ≤ 2 𝑛 1 2 ≤ 𝑛 1 . לכן האבא של כל איבר מ- 𝐻 2 הוא איבר מהערימה 𝐻 1 . מכיוון שכל האיברים מ- 𝐻 1 קטנים מהאיברים של 𝐻 2 , הערימה עדיין חוקית. אם 𝑛 2 > 𝑛 1 : נבנה ערימה חדשה עם כל האיברים של 𝐻 1 , 𝐻 2 בזמן 𝑛1 + 𝑛2 = 𝑂 2𝑛2 =𝑂 𝑛 2 .
23
שאלה 5 הציעו אלגוריתם עם זמן ריצה 𝑂 𝑛⋅𝑙𝑜𝑔 𝑘 למיזוג k מערכים ממויינים 𝐴 1 ,…, 𝐴 𝑘 לכדי מערך אחד. מספר האיברים הכולל הוא n. ניתן להניח שמתקיים 𝑘≤𝑛.
24
שאלה 5 הציעו אלגוריתם עם זמן ריצה 𝑂 𝑛𝑙𝑜𝑔 𝑘 למיזוג k מערכים ממויינים 𝐴 1 ,…, 𝐴 𝑘 לכדי מערך אחד (שנקרא לו M). תשובה: נשתמש בערימת מינימום של k שלשות מהצורה: 𝑑, 𝑖, 𝐴 𝑑 𝑖 , עבור 1≤𝑑≤𝑘, 1≤𝑖≤𝑛 הערימה תמומש ע"י מערך B (בפסאודו קוד שנראה). תחילה נבנה את הערימה ע"י שימוש באלמנט הראשון מכל אחד מ-k המערכים ב-𝑂 𝑘 בכל צעד – נבצע ExtractMin() מהערימה ונכניס את המפתח שיצא בסוף מערך הפלט M אם המערך שממנו הגיע האלמנט שהוצא מהערימה אינו ריק, נסיר ממנו את האיבר המינימלי ונכניסו לערימה.
25
שאלה 5 for d1 to k B[d] (d, 1, Ad[1]) Build-Heap(B) /*By the order of Ad [1] */ for j=1 to n (d, i, x) Extract-Min(B) M[j]x if i < Ad.length then Heap-Insert(B,(d, i+1, Ad[i+1])) Worst case time analysis: Build-Heap: O(k) Extract-Min: n times O(log k) Heap-Insert: n times O(log k) Total O(nlogk)
26
Quicksort algorithm Sort properties Selection
27
Quicksort - הרעיון pivot שיטת הפרד ומשול
בוחרים איבר במערך שיהיה ה-pivot, ומחלקים את האיברים במערך לשתי קבוצות: (< pivot) and (> pivot) pivot (<pivot) LEFT group (> pivot) RIGHT group
28
האלגוריתם quickSort( A, low, high ) if(high > low)
pivot ← partition(A, low, high) quickSort(A, low, pivot-1 ) quickSort(A, pivot+1, high) int partition( A, low, high ) pivot_value ← A[low] left ← low pivot ← left right ← high while ( left < right ) // Move left while item < pivot while( left < high && A[left] ≤ pivot_value) left++ // Move right while item > pivot while( A[right] > pivot_value) right-- // Make sure right has not passed left if( left < right ) SWAP(A, left, right) // right is final position for the pivot A[low] ← A[right] A[right] ← pivot_item return right quickSort(A, 0, length(A)-1)
29
דוגמה 10 9 5 2 6 8 3 7 1 4 Left Pivot Right // Move left while item < pivot while( left < high && A[left] ≤ pivot_value) left++
30
דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move left while item < pivot while( left < high && A[left] ≤ pivot_value) left++
31
דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move left while item < pivot while( left < high && A[left] ≤ pivot_value) left++
32
דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--
33
דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--
34
דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--
35
דוגמה 10 9 5 6 8 3 1 4 7 2 Pivot Left Right if( left < right ) \\Make sure right has not passed left SWAP(A, left, right)
36
דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Left Right // Move left while item < pivot while( left < high && A[left] ≤ pivot_value) left++
37
דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Left Right // Move left while item < pivot while( left < high && A[left] ≤ pivot_value) left++
38
דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--
39
דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Right Left // Move right while item > pivot while( A[right] > pivot_value) right--
40
דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Right Left // Move right while item > pivot while( A[right] > pivot_value) right--
41
דוגמה 10 9 5 7 6 8 2 1 4 3 Pivot Right Left // right is final position for the pivot A[low] ← A[right] A[right] ← pivot_value return right
42
דוגמה 10 9 5 7 6 8 4 2 1 3 2 1 3 10 9 5 7 6 8 3 2 1 10 9 8 7 6 5 . 10 9 8 7 6 5 4 3 2 1
43
?Why Quicksort זמן ריצה: במקרה הגרוע - 𝑂 𝑛 2 במקרה הממוצע - 𝑂 𝑛⋅ log 𝑛
במקרה הגרוע - 𝑂 𝑛 2 במקרה הממוצע - 𝑂 𝑛⋅ log 𝑛 למה בפועל משתמשים בו ולא ב-merge-sort שמבטיח ריצה בזמן 𝑂 𝑛⋅ log 𝑛 ? (ראיתם בכיתה ש) בפועל זמן הריצה קרוב לזה של המקרה הטוב. הקבועים ב-Quicksort קטנים מאלו שב- merge-sort למשל, ולכן ברוב המקרים ירוץ מהר יותר. היתרון הגדול של Quicksort שזהו אלגוריתם in place והוא לא דורש זיכרון נוסף, לעומת merge-sort המקצה מערכים נוספים. In place algorithms: needs at most 𝑂 log 𝑛 amount of extra storage space, beyond the items being sorted.
44
Quicksort stable sorting algorithms: maintain the relative order of records with equal keys Is the QuickSort version above stable? (What would happen in this array?) This version of QuickSort is NOT stable 10 9 2r 2l 3 8 7r 7l 1 4 10 9 7l 7r 8 3 2l 2r 1 4
45
שאלה 1 נתונה קבוצה של n איברים S, בה אותו איבר יכול להופיע יותר מפעם אחת, ואינדקס k ((1 ≤ k ≤ n. האיבר ה-k-י הוא האיבר שיימצא במקום ה-k אם נמיין את האיברים. הציעו אלגוריתם שמוצא את האיבר ה-k-י ב-O(n) זמן בממוצע. לדוגמה: {6, 3, 2, 4, 1, 1, 2, 6} האיבר ה-4 הוא 2 מכיוון שהוא נמצא במיקום 4 בקבוצה הממוינת: {1, 1, 2, 2, 3, 4, 6, 6}.
46
שאלה 1 - פתרון Select(k, S) // returns k-th element in S. pick x in S
partition S into: // Slightly different variant of partition() max(L) < x, E = {x}, x < min(G) if k ≤ length(L) // Searching for item ≤ x. return Select(k, L) else if k ≤ length(L) + length(E) // Found return x else // Searching for item ≥ x. return Select(k - length(L) - length(E), G) האלגוריתם מבוסס על אלגוריתם QuickSort x – האיבר ה k-בגודלו, pivot בכל שלב מחלקים את S ל-3 קבוצות: L- כל האיברים הקטנים מ-x E- כל האיברים השווים ל-x G- כל האיברים הגדולים מ-x אם לא מצאנו את x, ממשיכים לחפש אותו רקורסיבית ב-L או ב-G
47
שאלה 1 - פתרון במקרה הגרוע:
ה-pivot הנבחר x הוא האיבר המקסימלי במערך הנוכחי, ויש רק אחד כזה. G – קבוצה ריקה, |E|=1, n-1=|L| 𝑇 𝑛 = 𝑇 𝑛−1 +𝑂 𝑛 𝑛≤𝑘 𝑘 𝑛=𝑘 פתרון נוסחת הנסיגה: 𝑇 𝑛 =𝑂( 𝑛 2 ) במקרה הממוצע: בדומה ל-Quicksort, חצי מהאיברים ב-S הם טובים כ-pivot, לכן הגודל של G וL- יהיה קטן מ- 3 4 𝑛 𝑇 𝑛 ≤𝑇 3 4 𝑛 +𝑂 𝑛 =𝑂(𝑛) (שיטת המאסטר)
48
שאלה 2 בהינתן מערך בגודל n, הציעו אלגוריתם בזמן צפוי של Θ(𝑛) שקובע האם קיים מספר שמופיע יותר מ-n/2 פעמים אבחנה: אם x מופיע יותר מ-n/2, אז הוא המספר ה- 𝑛/2 +1 בגודלו במערך
49
שאלה 2 - פתרון
50
שאלה 3 n נתונים שמורים במערך A בגודל n. הציעו אלגוריתם למיון בזמן O(n) במקרה הגרוע, בלי תוספת זכרון, עבור המקרה בו: כל המפתחות הם 0 או 1 תשובה: מיון Quicksort, כאשר אנו משתמשים בשיטת ה-partition שראינו בשאלה 1 עם pivot=0. אחרי השלמה פונקצית ה-partition, המערך יהיה ממוין: L={}, E will have all elements with key 0, G will have all elements with key 1 ניתוח זמן ריצה - 𝜃 𝑛 , העלות של ביצוע partition פעם אחת
51
שאלה 3 n נתונים שמורים במערך A בגודל n. הציעו אלגוריתם למיון בזמן O(n) במקרה הגרוע, בלי תוספת זכרון, עבור המקרה בו: כל המפתחות הם בטווח [1..k] (k קבוע) תשובה: מיון Quicksort, עם pivot=1 מיון Quicksort, עם pivot=2 ... מיון Quicksort, עם pivot=k-1 אחרי k-1 צעדים המערך יהיה ממויין ניתוח זמן ריצה - 𝑂 𝑘⋅ 𝑛 =𝑂 𝑛 העלות של ביצוע k פעמים partition
52
שאלה 4 Given the following algorithm to sort an array A of size n:
Sort recursively the first 2/3 of A 𝐴 1.. 2𝑛 3 Sort recursively the last 2/3 of A 𝐴 𝑛 𝑛 * If 2𝑛 3 is not a natural number, round it up. Prove the above algorithm sorts A and find a recurrence 𝑇 𝑛 , expressing it's running time
53
שאלה 4 - פתרון The basic assumption is that after the first 2 steps, the 𝑛 3 largest number are in their places, sorted in the last third of A. In the last stage, the algorithm sorts the left 2 thirds of A. 𝑇(𝑛)= 3𝑇 2𝑛 3 =3 3𝑇 4𝑛 9 =… = 3 𝑖 ⋅𝑇 𝑖 𝑛 after 𝑖= log 𝑛 steps… T n = O n log (also according to the Master-Theorem)
54
שאלה 5 נתון מערך עם M+N איברים. N האיברים הראשונים ממויינים, ו-M האיברים האחרונים אינם ממויינים. עבור כל אחד מהמקרים הבאים הציעו שיטה (או שילוב של שיטות) למיון יעיל בזמן הגרוע. M=O(1) מיון הכנסה ב-O(N)
55
שאלה 5 נתון מערך עם M+N איברים. N האיברים הראשונים ממויינים, ו-M האיברים האחרונים אינם ממויינים. עבור כל אחד מהמקרים הבאים הציעו שיטה (או שילוב של שיטות) למיון יעיל בזמן הגרוע. 𝑀=𝑂 log 𝑁 מיין את M ב-merge sort – O(MlogM) אחד (merge) את שני החלקים – O(M+N) סה"כ זמן ריצה 𝑂 𝑀⋅ log 𝑀 +𝑁 =𝑂 𝑁
56
שאלה 5 נתון מערך עם M+N איברים. N האיברים הראשונים ממויינים, ו-M האיברים האחרונים אינם ממויינים. עבור כל אחד מהמקרים הבאים הציעו שיטה (או שילוב של שיטות) למיון יעיל בזמן הגרוע. M=O(N) מיין את כל המערך ב-merge sort – 𝑂 𝑀+𝑁 ⋅ log 𝑀+𝑁 =𝑂 𝑁⋅ log 𝑁 הזמן של quicksort יהיה O(N2) במקרה הגרוע, ולכן לא נשתמש בו.
57
שאלה 6 איך ניתן להשתמש באלגוריתם מיון שאינו יציב U (לדוגמה, מיון מהיר), לבניית אלגוריתם מיון יציב S עם אותו זמן ריצה של אלגוריתם U? הרעיון (פתרון מלא ב-PDF): Add a new field, index, to each element. This new field holds the original index of that element in the unsorted array. Change the comparison operator so that: [key1, index1] < [key2, index2] ⇔ key1 < key2 or ( key1 = key2 and index1 < index2) [key1, index1] > [key2, index2] ⇔ key1 > key2 or (key1 = key2 and index1 > index2) Execute the sorting algorithm U with the new comparison operation.
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.