7 memoization quicksort n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה PowerPoint Presentation
Download Presentation
תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה

Loading in 2 Seconds...

play fullscreen
1 / 41

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


  • 203 Views
  • Uploaded on

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

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה' - luann


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide2
סדרת פיבונצ'י
  • לאונדרדו מפיזה הידוע בשמות ליאונדרו פיזאנו, ליאונרדו בונאצ'י, או בפשטות פיבונצ'י נחשב בעיני רבים לגדול המתמטיקאים של ימי הביניים.
  • על שמו קרויה סדרת המספרים הבאה (בניגוד לדעה הרווחת הוא לא המציא אותה, רק השתמש בה):
  • סדרה זו מופיעה בטבע בצורות מפתיעות:

http://en.wikipedia.org/wiki/Fibonacci_number

slide3
חישוב המספר ה-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));

}

}

רקורסית זנב?

לא!

slide4

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’)

ברישום הבא, מובא עץ הקריאות לפונקציה כאשר ניתן לראות כי ישנם מספר חישובים שמתבצעים יותר מפעם אחת (אלו המודגשים בצבע):

slide5

ניתן לחסוך את החישובים המיותרים ע"י שמירת תוצאות של חישובים שבוצעו:

שמירה של תוצאות ביניים ב lookup tables כך שחישוב יתבצע פעם אחת לכל היותר.

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

הערכים נשמרים בטבלה לפי ה input. כלומר, לכל קלט אפשרי יש כניסה מתאימה בטבלה.

slide6

דוגמא

בכדי ליעל את Fib נשתמש בטכניקת ה memoization לשמירת תוצאות החישובים שבוצעו.

נראה תוכנית המחשבת את האיבר ה n-י בסדרת פיבונאצ'י, אשר משתמשת בטכניקת ה memoization השומרת תוצאות של חישובים רקורסיביים.

במקרה זה ה lookup table הינה מערך חד מימדי, כך שתא בעל אינדקס במערך, מכיל את הערך . באם ערך זה עדיין לא חושב, יכיל תא זה את הערך 1-.

slide7

publicclass FibMemo{

publicstaticvoid main(String[] args){

int n = 20;

System.out.println("fibMemo("+n+") =

"+fibMemo(n));

}

publicstaticint fibMemo(int n){

int[] lookupTable = newint[n+1];

for (int i=0; i < lookupTable.length ; i=i+1)

lookupTable[i] = -1; //EMPTY

return fibMemo(lookupTable, n);

}

publicstaticint fibMemo(int[] lookupTable, int n){

if (n==0)

lookupTable[n]= 0;

if (n==1)

lookupTable[n]= 1;

if (lookupTable[n]==-1)//EMPTY

lookupTable[n] = fibMemo(lookupTable,n-1) +

fibMemo(lookupTable,n-2);

return lookupTable[n];

}

}

והפתרון:

slide8

Divide-and-Conquer

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

מיון מהיר (Quick Sort)

  • חלוקת המערך לשני חלקים לפי ציר (pivot) שנבחר מחדש בכל שלב של הרקורסיה ומיון רקורסיבי של כל צד
  • הציר שנבחר הינו הערכה (ניחוש) של החציון של המספרים במערך
  • תזכורת: חציון הוא מדד למיקום המרכז של קבוצת נתונים מספריים. לדוגמא: החציון של קבוצת המספרים 1, 2, 22, 7, 19, 8, 16 הוא 8
  • נבחר בקוד שלנו את האיבר הראשון כציר.
quicksort example
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:
  • http://www.youtube.com/watch?v=2HjspVV0jK4
  • http://www.youtube.com/watch?v=o2dm4X-t8L0&
  • http://www.youtube.com/watch?v=FSyr8o8jjwM
slide12

מיון מהיר – הקוד

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

slide13

מיון מהיר – הקוד (המשך)

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();

}

slide14

מיון מהיר – הקוד (המשך)

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);

}

}

slide15

מיון מהיר – הקוד (המשך)

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)

i=i+1;

while(arr[j] > pivot)

j=j-1;

if (i<j)

swap(arr,i,j);

}

swap(arr,start,j);

return j;

}

slide16
דוגמה 2
  • בהינתן מספר מספר 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”}
slide17
השלם את הפונקציה

publicstatic String[] binaryNums(int n){

String[] answer;

if (n==0){

answer = new String[1];

answer[0]="";

}

else{

//

// Your code here

//

}

return answer;

}

17

slide19

רעיון של הרקורסיה

n=3

n=2

“0” + “”

“1” + “”

0

0

1

n=1

“”

n=0

slide20

רעיון של הרקורסיה

n=3

00

01

10

11

n=2

0

1

n=1

“”

n=0

slide21

רעיון של הרקורסיה

n=3

000

001

010

011

100

101

110

111

n=2

00

01

10

11

0

1

n=1

“”

n=0

slide22
הקוד

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;

}

22

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

i = האינדקס שלפיו מחלקים את המחרוזת

““, “a” + “b” + “c” +”d”

i=1

i=0

d, “a” + “b” + “c”

output:

abcd

cd, “a” + “b”

i=0

cd, “a” + “b”

bcd, “a”

i=0

bcd, “a”

i=0

abcd,””

abcd,””

slide25
הרעיון של הרקורסיה

““, “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,””

slide26
הרעיון של הרקורסיה

““, “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,””

slide27
הרעיון של הרקורסיה

““, “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”

slide28
הרעיון של הרקורסיה

““, “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”

. . .

slide29

קוד של דוגמה 3: הדפסת הפרמוטציות של מחרוזת

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,"");

}

slide30

קוד של דוגמה 3: הדפסת הפרמוטציות של מחרוזת

/** 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));

}

slide31

פונק' עזר: 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());

}

slide32
דוגמה 4 - הרכבת סכום נתון ממשקולות

בהינתן מערך משקולות אי-שליליים ומשקל נוסף (משקל סכום), נרצה לבדוק האם ניתן להרכיב מהמשקולות משקל השווה למשקל הסכום הנתון.

  • דוגמא לקלט:weights={1,7,9,3} Sum = 12במקרה זה הפונקציה תחזיר true כי ניתן לחבר את המשקולות 9 ו 3 ולקבל את הסכום 12.
  • דוגמא לקלט: weights={1,7,9,3} Sum = 15במקרה זה הפונקציה תחזיר false כי לא ניתן לחבר משקולות לקבלת הסכום 15.
slide33
תיאור פתרון
  • נתבונן באיבר הראשון במערך. ייתכן שהוא ייבחר לקבוצת המשקולות שתרכיב את הפתרון ויתכן שלא.
  • אם הוא לא ייבחר (להיות כלול בסכום המהווה את משקל המטרה) – אזי נותר לפתור בעיה קטנה יותר והיא האם ניתן להרכיב את הסכום מבין המשקולות שנותרו במערך.
  • אם הוא ייבחר – אזי נותר לפתור בעיה קטנה יותר והיא האם ניתן להרכיב את הסכום שנותר מבין המשקולות שנותרו במערך.
  • וכנ"ל לגבי יתר האיברים בצורה רקורסיבית.
slide34
תיאור פתרון - המשך
  • פתרון זה קל להציג כפונקציה רקורסיבית ,boolean calcWeights(int[] weights, int i, int sum )
  • הפונקציה מחזירה ערך אמת האם ניתן להרכיב את הסכום מבין קבוצת המשקולות שבתת המערך.
  • הפרמטרים:
    • weights – מערך המשקולות
    • sum – הסכום שיש להרכיב מהמשקולות
    • i – פרמטר נוסף הנחוץ עבור הרקורסיה. i הוא אינדקס במערך weights ויסמן את האיבר הנוכחי במערך עליו מתבצעת הקריאה הרקורסיבית.
slide35

i=0

50:

[10,20,30]

i=1

40:

[20,30]

50: [20,30]

i=2

20:

[30]

40: [30]

i=3

-10

[]

20:

[]

10:

[]

40:

[]

slide36

האם צריך לחשב

ענף ימני?

i=0

50:

[10,20,30]

i=1

40:

[20,30]

50:

[20,30]

50:

[30]

i=2

30:

[30]

i=3

50:

[]

0:

[]

30:

[]

20:

[]

4 calcweights
קוד דוגמה 4: calcWeights
  • הארגומנט i נחוץ עבור הרקורסיה – אך אינו באמת חלק מהקלט של הבעיה. בקריאה הראשונה ל calcWeights ערכו הוא 0. לכן נוסיף פונקצית מעטפת עם חתימה פשוטה יותר.

// An envelope function, without i argument

// A simpler signature

public static boolean calcWeights(int[] weights, int sum) {

return calcWeights(weights , 0, sum);

}

slide38
פתרון (המשך)

publicstaticboolean calcWeights(int[] weights,

int i, int sum) {

boolean res = false;

if (sum == 0)

res = true;

elseif (i >= weights.length)

res = false;

else

res = calcWeights(weights,i+1,sum-weights[i]) || calcWeights(weights, i + 1, sum);

return res;

}

slide39
דוגמה אחרונה
  • הפונקציה void subsetsSum(int[] weights, int sum) מקבלת מערך weights של משקולות (ערכים שלמים חיוביים) ומשקל שלם sum חיובי ומדפיסה את כל תתי הקבוצות של איברי המערך weights שסכומם sum.
  • דוגמא עבור weights={1,2,3,4,5} ו sum=10, הפונקציה תדפיס:
  • 1 2 3 4
  • 1 4 5
  • 2 3 5
slide40
דוגמה אחרונה
  • שאלה זו דומה מאוד לשאלת הרכבת סכום נתון ממשקולות. נסו להשלים את הפונקציות לבד.

public static void subsetsSum(int[] weights, int sum){

subsetsSum(________השלימו את החסר___);

}

public static void subsetsSum( ){

השלימו את החסר

}

slide41
דוגמה אחרונה: פתרון

publicstaticvoid subsetsSum(int[] weights, int sum){

subsetsSum(weights, sum,0,””);

}

publicstaticvoid subsetsSum(int[] weights, int sum, int index, String acc){

if(sum == 0)

System.out.println(acc);

elseif (sum > 0 & index < weights.length){

subsetsSum(weights,sum-weights[index], index+1,acc + weights[index] + ' ');

subsetsSum(weights,sum,index+1,acc);

}

}

41