Presentation is loading. Please wait.

Presentation is loading. Please wait.

Huffman code QuickSort

Similar presentations


Presentation on theme: "Huffman code QuickSort"— Presentation transcript:

1 Huffman code QuickSort
תרגול 10 Huffman code QuickSort

2 Huffman code קוד הופמן – אלגוריתם קידוד לכיווץ נתונים שמשתמש בתור עדיפות לקביעת הקידוד. תכונות האלגוריתם – בהינתן מידע המורכב מקבוצת סמלים C (לדוגמה C יכולה להיות קבוצת האותיות בשפה כלשהי + סימני פיסוק) האלגוריתם משתמש בתור עדיפות כדי לקבוע אילוי קידודים לתת לסמלים השונים בקבוצה. האלגוריתם בונה עץ בינארי (עץ הופמן) שבו הסמלים משויכים לעלים, ואורך הקידוד של סמל הוא עומק העלה אליו הוא משויך. כדי למצוא את הקידוד של סמל כלשהו, נתחיל בשורש ונלך במסלול עד לעלה אליו הוא משויך. נוסיף 0 כל פעם שעברנו לבן השמאלי ו1 כל פעם שעברנו לבן הימני הקידוד שנוצר הוא אופטימלי (מבין הקידודים המקודדים כל סמל בנפרד)

3 פסאודו-קוד לבניית העץ Huffman (C) n ← |C|
Q ← { new priority queue for the letters in C } for i ← 1 to n-1 z ← allocate new node x ← Extract_Min(Q) y ← Extract_Min(Q) z.left ← x z.right ← y frequency (z) ← frequency (x) + frequency (y) Insert(Q, z)

4 דוגמה Example Huffman tree with 4 symbols (C={e,s,x,y})
Frequencies: x=1 y=1 s=7 e=20 Encoding: e: 1 s: x: y: 001

5 שאלה 1 מהו קוד הופמן האופטימלי עבור רצף התדירויות הבא, המבוסס על 8 מספרי פיבונאצ'י הראשונים a:1 b:1 c:2 d:3 e:5 f:8 g:13 h:21 הכלילו את תשובתכם לכדי מציאת קוד הופמן האופטימלי כאשר התדירויות הנתונות הן עבור n מספרי פיבונאצ'י הראשונים

6 שאלה 1 מהו קוד הופמן האופטימלי עבור רצף התדירויות הבא, המבוסס על 8 מספרי פיבונאצ'י הראשונים a:1 b:1 c:2 d:3 e:5 f:8 g:13 h:21 תשובה: מאחר וישנן 8 תדירויות (8 אותיות ב-א"ב), גודל התור ההתחלתי יהיה n=8, ויידרשו 7 מיזוגים לשם בניית העץ. העץ הסופי ייצג את הקידוד האופטימלי. מילת-הקוד עבור כל אות היא רצף התוויות שעל הצלעות (צלע לבן שמאלי – 0, צלע לבן ימני – 1) במסלול שמוביל מהשורש לעלה שמייצג את האות.

7 שאלה 1 מהו קוד הופמן האופטימלי עבור רצף התדירויות הבא, המבוסס על 8 מספרי פיבונאצ'י הראשונים a:1 b:1 c:2 d:3 e:5 f:8 g:13 h:21 תשובה: h : g : 1 f : e : d : c : b: a:

8 שאלה 1 הכלילו את תשובתכם לכדי מציאת קוד הופמן האופטימלי כאשר התדירויות הנתונות הן עבור n מספרי פיבונאצ'י הראשונים תשובה: ניתן לראות שבסעיף הקודם העץ שהתקבל הוא למעשה ענף אחד ארוך שעליו תלויים הרבה עלים. זה נכון למספרי פיבונאצ'י באופן כללי, שכן מתכונת הרקורסיה של פיבונאצ'י נובע ש: 𝐹 𝑛+2 = 𝑖=0 𝑛 𝐹 𝑖 +1

9 𝐹 𝑛+2 = 𝐹 𝑛+1 + 𝐹 𝑛 = 𝑖=0 𝑛−1 𝐹 𝑖 +1+ 𝐹 𝑛 = 𝑖=0 𝑛 𝐹 𝑖 +1
שאלה 1 הכלילו את תשובתכם לכדי מציאת קוד הופמן האופטימלי כאשר התדירויות הנתונות הן עבור n מספרי פיבונאצ'י הראשונים תשובה: ניתן להוכיח זאת באמצעות אינדוקציה: המספרים 1,1,2,3 מהווים את הבסיס נניח את נכונות הטענה לכל מספרי פיבונאצ'י שקטנים מ- 𝐹 𝑛+2 צעד: הוכחת נכונות עבור 𝐹 𝑛+2 𝐹 𝑛+2 = 𝐹 𝑛+1 + 𝐹 𝑛 = 𝑖=0 𝑛−1 𝐹 𝑖 +1+ 𝐹 𝑛 = 𝑖=0 𝑛 𝐹 𝑖 +1 לכן מתקיים 𝐹 𝑛+2 > 𝑖=0 𝑛 𝐹 𝑖 , וברור שמתקיים 𝐹 𝑛+2 > 𝐹 𝑛+1 לכן 𝐹 𝑛+2 נבחר אחרי כל מספרי פיבונאצ'י שקטנים ממנו כבר אוחדו לעץ אחד. 𝐹 𝑘+2 = 𝑖=0 𝑘 𝐹 𝑖 +1

10 שאלה 2 בהינתן סדרת התדירויות הבאה עבור קוד הופמן: 𝑓 𝑖 = 4 𝑖=1 2 𝑖 𝑖∈ 2..𝑛 ציירו את המבנה של עץ הופמן שמתאר את הסדרה. פתרון: הסבר: באופן דומה לסדרת פיבונאצ'י, ניתן לראות שמתקיים 𝑓 𝑗 = 𝑓 1 + 𝑓 2 +…+ 𝑓 𝑗−1 לכן, בכל שלב בבניית העץ נבחר את השורש של תת-העץ 𝑓 1 −−− 𝑓 𝑖−1 שכבר נוצר, ונקבל את העץ בדיאגרמה.

11 שאלה 2 מצאו רשימת תדירויות כך שעץ הופמן עבור רשימה זו יבנה בצורה דטרמיניסטית את המבנה הבא: תשובה (דוגמה): 2,2,3,5,5,5 22 10 12 7 4 5 5 5 3 2 2

12 שאלה 2 מצאו נוסחת תדירויות כך שקוד הופמן עבור תדירויות אלו יבנה בצורה דטרמיניסטית את המבנה הבא: תשובה: בכדי ליצור את המבנה הזה, נרצה ששני האלמנטים הבאים בסדרה ייבחרו לפני האיחוד עם תת העץ שכבר קיים. התבנית של הסדרה מבוססת על העקרון שבכל רמה, התדירות של שני האלמנטים הבאים קטנה מסכום התדירויות עד לאותו רגע.

13 שאלה 2 מצאו נוסחת תדירויות כך שקוד הופמן עבור תדירויות אלו יבנה בצורה דטרמיניסטית את המבנה הבא: לדוגמה: 𝑓 𝑖 = 𝑠𝑜𝑚𝑒 𝑐𝑜𝑛𝑠𝑡𝑎𝑛𝑡 𝑐≥1 𝑖≤4 𝑓 𝑖−1 𝑖 𝑖𝑠 𝑒𝑣𝑒𝑛 3 𝑖−3 2 𝑒𝑙𝑠𝑒 הפונקציה הנ"ל יוצרת, למשל, את הסדרה 1,1,1,1,3,3,9,9,27,27,81,81,…

14 Quicksort

15 Quicksort - הרעיון pivot שיטת הפרד ומשול
(< pivot) and (> pivot) pivot (<pivot) LEFT group (> pivot) RIGHT group

16 האלגוריתם 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, low, high ) if(high > low) pivot ← partition(A, low, high) quickSort(A, low, pivot-1 ) quickSort(A, pivot+1, high) ביצוע מיון לכל המערך יתבצע ע"י הקריאה quickSort(A, 0, length(A)-1)

17 דוגמה 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++

18 דוגמה 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++

19 דוגמה 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++

20 דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--

21 דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--

22 דוגמה 10 9 5 2 6 8 3 7 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--

23 דוגמה 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)

24 דוגמה 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++

25 דוגמה 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++

26 דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Left Right // Move right while item > pivot while( A[right] > pivot_value) right--

27 דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Right Left // Move right while item > pivot while( A[right] > pivot_value) right--

28 דוגמה 10 9 5 7 6 8 3 2 1 4 Pivot Right Left // Move right while item > pivot while( A[right] > pivot_value) right--

29 דוגמה 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

30 דוגמה 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

31 ?Why Quicksort זמן ריצה: במקרה הגרוע – O(n^2) במקרה הממוצע - O(nlogn)
למה משתמשים בו בפועל ולא בmerge-sort שמבטיח ריצה בזמן O(nlogn)? ראיתם בכיתה, כי בפועל זמן הריצה קרוב לזה של המקרה הטוב. הקבועים ב-Quicksort קטנים מאלו שב- merge-sort למשל, ולכן ברוב המקרים ירוץ מהר יותר. היתרון הגדול של Quicksort שזהו אלגוריתם in place והוא לא דורש זיכרון נוסף, לעומת merge-sort המקצה מערכים נוספים. in place algorithms: need small, constant amount of extra storage space, beyond the items being sorted.

32 Quicksort stable sorting algorithms: maintain the relative order of records with equal keys Is the QuickSort version above stable? No

33 שאלה 3 נתונה קבוצה של 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}.

34 שאלה 3 - פתרון 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) x – האיבר ה k-בגודלו, pivot בכל שלב מחלקים את S ל-3 קבוצות: L- כל האיברים הקטנים מ-x G- כל האיברים הגדולים מ-x E- כל האיברים השווים ל-x אם לא מצאנו את x, ממשיכים לחפש אותו רקורסיבית ב-L או ב-G

35 שאלה 3 - פתרון במקרה הגרוע:
ה-pivot הנבחר x הוא האיבר המקסימלי במערך הנוכחי, ויש רק אחד כזה. G – קבוצה ריקה, |E|=1, n-1=|L| 𝑇 𝑛 = 𝑇 𝑛−1 +𝑂 𝑛 𝑛>𝑘 𝑘 𝑛=𝑘 פתרון נוסחת הנסיגה: 𝑇 𝑛 =𝑂( 𝑛 2 ) במקרה הממוצע: בדומה ל-Quicksort, חצי מהאיברים ב-S הם טובים כ-pivot, לכן הגודל של הממוצע G וL- יהיה קטן מ 3 4 𝑛 𝑇 𝑛 ≤𝑇 3 4 𝑛 +𝑂 𝑛 =𝑂(𝑛) )שיטת המאסטר(

36 שאלה 4 במערך בגודל n, הציעו אלגוריתם בזמן צפוי של O(n) שקובע האם קיים מספר שמופיע יותר מ n/2 פעמים

37 שאלה 4 במערך בגודל n, הציעו אלגוריתם בזמן צפוי של O(n) שקובע האם קיים מספר שמופיע יותר מ n/2 פעמים אם x מופיע יותר מ n/2, אז הוא המספר ה 𝑛/2 +1 בגודלו במערך

38 שאלה 4

39 שאלה 5 הציעו אלגוריתם למיון בזמן O(n) במקרה הגרוע במקרה הבא (בלי תוספת זכרון): כל המפתחות הם 0 או 1 נבצע Partition עם pivot=0

40 שאלה 5 הציעו אלגוריתם למיון בזמן O(n) במקרה הגרוע במקרה הבא (בלי תוספת זכרון): כל המפתחות הם בטווח [1..k] (k קבוע) נבצע Partition עם pivot=1 נבצע Partition עם pivot=2 ... נבצע Partition עם pivot=k-1

41 שאלה 6 נתון אלגוריתם מיון חדש:
Sort recursively the first 2/3 of A (A[1..2n/3]) Sort recursively the last 2/3 of A (A[n/3..n]) אם 2 3 ∗n הוא לא מספר שלם אז נעגל אותו למעלה. הוכיחו את האלגוריתם הנ"ל (כלומר, להסביר שהוא עובד) והראו את זמן הריצה.

42 שאלה 6 Sort recursively the first 2/3 of A (A[1...2n/3]) Sort recursively the last 2/3 of A (A[n/3...n]) הוכחה: לאחר הצעד הראשון 1/3 האיברים הגדולים ביותר במערך נמצאים ב2/3 המקומות האחרונים במערך. לכן, לאחר הצעד השני 1/3 האיברים האחרונים גדולים מיתר האיברים במערך, והם ממוינים (בינם לבין עצמם) כלומר, 1/3 האיברים האחרונים הם הגדולים ביותר ויהיו ממוינים במקומם. לאחר מכן אנחנו ממיינים את 2/3 האיברים הנותרים, ולכן אנחנו מקבלים מערך ממוין.

43 שאלה 6 זמן ריצה: 𝑇 𝑛 = 3𝑇 2𝑛 3 נפתח בשיטת האיטרציה:
Sort recursively the first 2/3 of A (A[1..2n/3]) Sort recursively the last 2/3 of A (A[n/3+1..n]) זמן ריצה: 𝑇 𝑛 = 3𝑇 2𝑛 3 נפתח בשיטת האיטרציה: 𝑇 𝑛 = 3𝑇 2𝑛 3 = 3 3𝑇 4𝑛 9 = 𝑇 8𝑛 = … = 3 𝑖 𝑇 𝑖 𝑛 אחרי 𝑖= log 𝑛 צעדים: 𝑇 𝑛 = 3 log 𝑛 ·𝑇 1 =…= 𝑛 log לכן 𝑇 𝑛 =𝑂 𝑛 log (ניתן להגיע לזה גם בעזרת שיטת המאסטר)

44 שאלה 7 נתון מערך A עם M+N איברים. N האיברים הראשונים ממויינים, ו M האיברים האחרונים אינם ממויינים. מהו זמן הריצה במונחים של M,N במקרה הגרוע אם מבצעים מיון הכנסה (insertion sort) על A? פתרון: בעצם צריך לבצע הכנסה רק לM האיברים האחרונים. לכל אחד מהם לוקח 𝑂 𝑁+𝑀 לכן סה"כ 𝑂 𝑀 𝑁+𝑀 .

45 שאלה 7 נתון מערך A עם M+N איברים. N האיברים הראשונים ממויינים, ו M האיברים האחרונים אינם ממויינים. מהו זמן הריצה במונחים של M,N במקרה הגרוע אם מבצעים מיון הכנסה (insertion sort) על A? פתרון נוסף: ניתן לבצע insertion sort לM האיברים האחרונים בזמן 𝑂 𝑀 2 ואז לבצע איחוד בזמן 𝑂 𝑁+𝑀 סה"כ זמן ריצה 𝑂 𝑀 2 + 𝑀+𝑁 =𝑂 𝑀 2 +𝑁

46 שאלה 7 נתון מערך עם M+N איברים. N האיברים הראשונים ממויינים, ו M האיברים האחרונים אינם ממויינים. עבור כל אחד מהמקרים הבאים הציעו שיטה (או שילוב של שיטות) למיון יעיל בזמן הגרוע. M=O(1) מיון הכנסה ב O(N)

47 שאלה 7 נתון מערך עם M+N איברים. N האיברים הראשונים ממויינים, ו M האיברים האחרונים אינם ממויינים. עבור כל אחד מהמקרים הבאים הציעו שיטה (או שילוב של שיטות) למיון יעיל בזמן הגרוע. M=O(logN) מיין את M בmerge sort – O(MlogM) אחד (merge) את שני החלקים – O(M+N) סה"כ זמן ריצה 𝑂 𝑀 log 𝑀 + 𝑀+𝑁 =𝑂 𝑀 log 𝑀 +𝑁 𝑀 log 𝑀 +𝑁 =𝑂 𝑁

48 שאלה 7 נתון מערך עם M+N איברים. N האיברים הראשונים ממויינים, ו M האיברים האחרונים אינם ממויינים. עבור כל אחד מהמקרים הבאים הציעו שיטה (או שילוב של שיטות) למיון יעיל בזמן הגרוע. M=O(N) מיין את כל המערך בmerge sort – O(NlogN) הזמן של quicksort במקרה הגרוע יהיה O(N2), ולכן לא נשתמש בו

49 שאלה 8 הציעו שיטה להפוך אלגוריתם מיון מבוסס השוואות לא יציב A לאלגוריתם יציב A’. פתרון: לכל איבר נוסיף את האינדקס שלו כך שיהיו זוג (key,index). מיין את האיברים לפי: [key1, index1] < [key2, index2] ⇔key1 < key2 or ( key1 = key2 and index1 < index2) [key1, index1] > [key2, index2] ⇔key1 > key2 or (key1 = key2 and index1 > index2) הוספנו 𝑂 𝑛 זיכרון וזמן הריצה נשאר זהה לשל האלגוריתם A.

50 שאלה 8 הציעו שיטה להפוך אלגוריתם מיון מבוסס השוואות לא יציב A לאלגוריתם יציב A’. פתרון נוסף: נוסיף לכל איבר את האינדקס שלו. נריץ את אלגוריתם A הרגיל על המפתחות. לכל איבר המופיע יותר מפעם אחת נריץ מיון נוסף הפעם לפי האינדקס. זמן ריצה : שלב 3 – במקרה הגרוע אותו איבר מופיע בכל התאים ולכן זמן הריצה הוא 𝑂 𝑛 log 𝑛 סה"כ זמן הריצה 𝑂(𝑛 log 𝑛 )


Download ppt "Huffman code QuickSort"

Similar presentations


Ads by Google