1 / 33

תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה

תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה. סדרת פיבונצ'י. לאונדרדו מפיזה הידוע בשמות ליאונדרו פיזאנו, ליאונרדו בונאצ'י, או בפשטות פיבונצ'י נחשב בעיני רבים לגדול המתמטיקאים של ימי הביניים. על שמו קרויה סדרת המספרים הבאה (בניגוד לדעה הרווחת הוא לא המציא אותה, רק השתמש בה):

seitzb
Download Presentation

תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. תרגול מס' 7: MemoizationQuicksortתרגילים מתקדמים ברקורסיה

  2. סדרת פיבונצ'י • לאונדרדו מפיזה הידוע בשמות ליאונדרו פיזאנו, ליאונרדו בונאצ'י, או בפשטות פיבונצ'י נחשב בעיני רבים לגדול המתמטיקאים של ימי הביניים. • על שמו קרויה סדרת המספרים הבאה (בניגוד לדעה הרווחת הוא לא המציא אותה, רק השתמש בה): • סדרה זו מופיעה בטבע בצורות מפתיעות: http://en.wikipedia.org/wiki/Fibonacci_number

  3. חישוב המספר ה-n בסדרה: publicclass Fib { publicstaticint fib(int n){ int ans; if (n==0) ans = 0; elseif (n==1) ans = 1; else ans = fib(n-1)+fib(n-2); return ans; } publicstaticvoid main(String[] args){ int n = 20; System.out.println("fib("+n+") = "+fib(n)); } } רקורסית זנב? לא!

  4. fib(2) fib(1) fib(0) fib(5) fib(4) fib(3) fib(3) fib(2) fib(2) fib(1) fib(1) fib(1) fib(0) fib(1) fib(0) Memoization (without ‘r’) ברישום הבא, מובא עץ הקריאות לפונקציה כאשר ניתן לראות כי ישנם מספר חישובים שמתבצעים יותר מפעם אחת (אלו המודגשים בצבע):

  5. ניתן לחסוך את החישובים המיותרים ע"י שמירת תוצאות של חישובים שבוצעו: נשמור תוצאות ביניים ב lookup table-כך שחישוב יתבצע פעם אחת לכל היותר. לכל ערך שנרצה לחשב, נבדוק תחילה האם ערך זה חושב, כלומר, האם יש עבורו ערך מתאים ב lookup table. אם כן, נשתמש בערך זה. אחרת, נבצע את החישוב ונשמור את התוצאה בכניסה המתאימה בטבלה. הערכים נשמרים בטבלה לפי הקלט. כלומר, לכל קלט אפשרי יש כניסה מתאימה בטבלה.

  6. דוגמא בכדי ליעל את fib נשתמש בטכניקת הmemoization לשמירת תוצאות החישובים שבוצעו. נראה תוכנית המחשבת את האיבר ה n-י בסדרת פיבונאצ'י, ומשתמשת בטכניקה זו לשמירת תוצאות של חישובים רקורסיביים. במקרה זה ה lookup table הינה מערך חד מימדי, כך שהתא בעל אינדקס i במערך, מכיל את הערך עבור fib(i). באם ערך זה עדיין לא חושב, יכיל תא זה את הערך 1-.

  7. והפתרון: publicclass FibMemo{ publicstaticvoid main(String[] args) { int n = 20; System.out.println("fib("+n+") = “ + fib(n)); } publicstaticint fib(int n) { int[] lookupTable = newint[n+1]; for (int i=0; i < lookupTable.length ; i=i+1) lookupTable[i] = -1; //EMPTY return fib(lookupTable, n); } publicstaticint fib(int[] lookupTable, int n) { if (n==0) lookupTable[n]= 0; if (n==1) lookupTable[n]= 1; if (lookupTable[n]==-1)//EMPTY lookupTable[n] = fib (lookupTable,n-1) + fib(lookupTable,n-2); return lookupTable[n]; } }

  8. fib(2) fib(1) fib(0) fib(5) fib(4) fib(3) fib(3) fib(2) fib(2) fib(1) fib(1) fib(1) fib(0) fib(1) fib(0) Memoization כעת עץ הקריאות לפונקציה יראה כך:

  9. Divide-and-Conquer • טכניקת ה Divide-and-Conquer מבוססת על רעיון דומה לפתרון רקורסיבי של בעיות: • חלק את הבעיה המקורית לתתי בעיות קטנות (שניים או יותר) - Divide • פתור כל תת בעיה – Conquer • צרף את תתי הפתרונות לפתרון לבעיה המקורית. • ישנם אלגוריתמים רבים המתוכננים לפי עיקרון זה, עליהם נמנים האלגוריתמים הבאים: • Mergesort • Quicksort

  10. מיון מהיר (Quick Sort) • חלוקת המערך לשני חלקים לפי ציר (pivot) שנבחר מחדש בכל שלב של הרקורסיה ומיון רקורסיבי של כל צד • הציר שנבחר הינו הערכה (ניחוש) של החציון של המספרים במערך • תזכורת: חציון הוא מדד למיקום המרכז של קבוצת נתונים מספריים. לדוגמא: החציון של קבוצת המספרים 1, 2, 22, 7, 19, 8, 16 הוא 8 • נבחר בקוד שלנו את האיבר הראשון כציר.

  11. מיון מהיר (Quicksort) - דוגמא

  12. מיון מהיר – הקוד publicclass QuickSort { //…. publicstaticvoid quicksort(int[] arr){ quicksort(arr, 0, arr.length-1); } publicstaticvoid quicksort(int[] arr, int start, int end){ if (start<end){ int i = partition(arr, start, end); quicksort(arr, start, i-1); quicksort(arr, i+1, end); } } //….

  13. מיון מהיר – פונקציות עזר publicstaticvoid swap(int[] arr, int i, int j){ // swap arr[i] and arr[j] int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } publicstaticvoid initRandomArray(int[] arr){// shuffle the array arr int n = arr.length; for (int i = 0; i < n; i++) { arr[i] = (int) (Math.random() * 10 * n); } } publicstaticvoid printArray (int[] arr) { for (int i=0; i<arr.length; i=i+1) System.out.print (arr[i]+" "); System.out.println(); }

  14. מיון מהיר – partition publicstaticint partition(int[] arr, int start, int end){ int pivot = arr[start]; int i = start; int j = end; while(i<j){ while(i<end && arr[i] <= pivot) //scan upwards i=i+1; while(arr[j] > pivot) //scan downwards j=j-1; if (i<j) swap(arr,i,j); } swap(arr,start,j); //put pivot in place return j; }

  15. דוגמאת ריצה של partition pivot pivot Swap! j i i i j j end i j start j j i

  16. מיון מהיר – הקוד (המשך) import java.util.Scanner; publicclass QuickSort { publicstaticvoid main(String[] args){ Scanner sc = new Scanner(System.in); System.out.println("Enter number of elements to sort:"); int n = sc.nextInt(); int[] arr = newint[n]; // Initializes arr with random numbers // in [0..10*N) initRandomArray(arr); System.out.println("The input array:"); printArray(arr); quicksort(arr); System.out.println("The sorted array:"); printArray(arr); } //…. continued

  17. Quicksort Example • Example: • http://www.cise.ufl.edu/~ddd/cis3020/summer-97/lectures/lec17/sld001.htm • www.cs.auckland.ac.nz/software/AlgAnim/Java/q_sort/tqs_new.html • Video: • www.youtube.com/watch?v=ywWBy6J5gz8 • http://www.youtube.com/watch?v=o2dm4X-t8L0 • http://www.youtube.com/watch?v=2HjspVV0jK4 • http://www.youtube.com/watch?v=FSyr8o8jjwM

  18. הדפסת המחרוזות באורך n • בהינתן מספר n0 ≤, נרצה להחזיר מערך של 2n המחרוזות באורך n המורכבות מאפסים ואחדים.סדר המחרוזת הוא סדר המניה מאפס ל 2n-1 בבסיס 2. • הפלט עבור n=0: • {“”} • הפלט עבור n=1: • {“0”,”1”} • הפלט n=2: • {“00”,”01”,”10,”11”} • הפלט עבור n=3: • {“000”,”001”,”010”,”011”,“100”,”101”,”110”,”111”}

  19. השלימו את הפונקציה publicstatic String[] binaryNums(int n){ String[] answer; if (n==0){ answer = new String[1]; answer[0]=""; } else { // // Your code here // } return answer; } 19

  20. הרעיון של הרקורסיה n=3 n=2 n=1 n=0 “”

  21. רעיון של הרקורסיה n=3 n=2 “0” + “” “1” + “” 0 0 1 n=1 n=0 “”

  22. רעיון של הרקורסיה n=3 n=2 00 01 10 11 0 1 n=1 n=0 “”

  23. רעיון של הרקורסיה n=3 000 001 010 011 100 101 110 111 n=2 00 01 10 11 0 1 n=1 n=0 “”

  24. הקוד publicstatic String[] binaryNums(int n) { String[] answer; if (n==0){ answer = new String[1]; answer[0]=""; } else { String[] prev = binaryNums(n-1); answer = new String[2*prev.length]; for (int i =0;i<prev.length; i = i+1) { answer[i]= "0" + prev[i]; answer[prev.length + i] = "1“+ prev[i]; } } return answer; } 24

  25. הדפסת הפרמוטציות של מחרוזת • פרמוטציה של מחרוזת מוגדרת כמחרוזת המכילה את אותן אותיות, ייתכן שבשינוי סדר. נניח בדוגמה זו שכל האותיות שונות זו מזו. • למשל הפרמוטציות עבור המחרוזת bcd הם: • “bcd" • “bdc" • “cbd“ • “cdb” • “dbc“ • “dcb”

  26. הרעיון של הרקורסיה ““, “a” + “b” + “c” +”d” i=0 i=1 d, “a” + “b” + “c” output: abcd cd, “a” + “b” i=0 cd, “a” + “b” bcd, “a” i=0 bcd, “a” נרוץ עם i מ0 עד גודל המחרוזת ועבור כל i נבחן את כל המחרזות האפשריות בהן התו הi הוא הראשון כך שבכל קריאה i הוא האינדקס של האות הבאה אותה מצרפים למחרוזת i=0 abcd,”” abcd,””

  27. הרעיון של הרקורסיה ““, “a” + “b” + “c” +”d” i=1 d, “a” + “b” + “c” output: abcd cd, “a” + “b” i=0 i=1 cd, “a” + “b” i=0 bcd, “a” bcd, “a” i=0 abcd,”” abcd,””

  28. הרעיון של הרקורסיה ““, “a” + “b” + “c” +”d” d, “a” + “b” + “c” output: abcd i=1 i=2 cd, “a” + “b” cd, “a” + “b” “”, “a” + “b” + “d” + “c” i=0 c, “a” + “b” + “d” output: abdc bcd, “a” bcd, “a” i=0 abcd,”” abcd,””

  29. הרעיון של הרקורסיה ““, “a” + “b” + “c” +”d” d, “a” + “b” + “c” output: abcd i=1 cd, “a” + “b” cd, “a” + “b” i=1 “”, “a” + “b” + “d” + “c” i=1 c, “a” + “b” + “d” output: abdc bcd, “a” bcd, “a” i=0 abcd,”” abcd,”” bd, “a” + “c” bd, “a” + “c” d, “a” + “c” + “b” output: acbd “”, “a” + “c” + “b” + “d”

  30. הרעיון של הרקורסיה ““, “a” + “b” + “c” +”d” d, “a” + “b” + “c” output: abcd cd, “a” + “b” cd, “a” + “b” “”, “a” + “b” + “d” + “c” i=3 c, “a” + “b” + “d” output: abdc bcd, “a” bcd, “a” abcd,”” abcd,”” bd, “a” + “c” bd, “a” + “c” d, “a” + “c” + “b” . . . bc, “a” + “d” output: acbd “”, “a” + “c” + “b” + “d” . . .

  31. קוד הדפסת הפרמוטציות של מחרוזת public static void perms(String s){ // We call the method perm(s,"") which prints // the empty string followed by each permutation // of s the empty string. perms(s,""); }

  32. קוד הדפסת הפרמוטציות של מחרוזת /** Function prints all the permutation of a string. * Note: assume the string is a set (no duplicate * chars) */ // Prints string acc followed by all permutations of // string s1 publicstaticvoidperms(String s1, String acc){ if (s1.length()==0) System.out.println(acc); else for (int i=0; i<s1.length(); i=i+1) perms(delete(s1, i), acc +s1.charAt(i)); }

  33. פונק' עזר: delete // This function returns the string s with the i-th // character removed publicstatic String delete(String s, int i){ // Assumes that i is a position in the string return s.substring(0,i) + s.substring(i+1,s.length()); }

More Related