580 likes | 725 Vues
http://www.csie.nctu.edu.tw/~tsaiwn /java/. Programming in Java. More examples, … 蔡文能 交通大學資訊工程學系 tsaiwn@csie.nctu.edu.tw. Agenda. Computing factorial Loop method Recursive method Computing primes Sieve method Sorting an array Selection Sort Insertion Sort Bubble Sort Quick Sort
E N D
http://www.csie.nctu.edu.tw/~tsaiwn/java/ Programming in Java More examples, … 蔡文能 交通大學資訊工程學系 tsaiwn@csie.nctu.edu.tw
Agenda • Computing factorial • Loop method • Recursive method • Computing primes • Sieve method • Sorting an array • Selection Sort • Insertion Sort • Bubble Sort • Quick Sort • Merge Sort
Computing Factorial • The factorial of an integer is the product of that number and all of the positive integers smaller than it. • - 0! = 1 • - 1! = 1 • . . . • - 5! = 5*4*3*2*1 = 120 • - 6! = 6*5*4*3*2*1 = 720 • . . . • - 50! = • 30414093201713378043612608166064768844377641568960512000000000000
Factorial -- Iteration • public class Factorial { • public static long factorial(int n) { • long fact = 1; • for (int i =2; i <= n; i ++) //for Loop • fact *= i; //shorthand for fact=fact*i; • return fact; • } • } In separate files • public class ComputingFactorial { • public static void main(String arg[ ]) { • long a = Factorial.factorial(Integer.parseInt(arg[0])); • System.out.println("Factorial of " + arg[0] + "=" + a); • } • }
Recursion 遞迴概念 • 很久很久以前, 這裡有一座山, 山裡有一座廟, 廟裡有個老和尚和小和尚, 小和尚要老和尚說故事給他聽。老和尚就說:『很久很久以前, 這裡有一座山, 山裡友一座廟, 廟裡有個老和尚和小和尚, 小和尚要老和尚說故事給他聽。..... • 莊子與惠子游於濠梁之上。莊子曰:「鯈於出游從容,是魚之樂也。」 惠子曰:『子非魚焉知魚之樂?』 莊子曰:『子非我焉知我不知魚之樂?』 惠子曰:『子非我焉知我不知你不知魚之樂?』 莊子曰:『子非我焉知我不知你不知我知魚之樂?』 惠子曰:『子非我焉知我不知你不知我不知你不知魚之樂?』 莊子曰:『子非我焉知 ... !@#$%^&*? ...
Factorial – Recursion, in Java • /** • * This class shows a recursive method to compute factorials. This method • * calls itself repeatedly based on the formula: n! = n* (n-1)! • **/ • public class Factorial2 { • public static long factorial(int n) { • if (n == 1) return 1; • else return n*factorial(n - 1); • } • }
N Factorial ( Recursive版 ) long factorial(int n) { if( n < 0) return -factorial(-n); if( n ==1 || n==0) return 1; return n * factorial(n-1); } /*告訴我 n-1 階乘, 我就給你 n 階乘*/ #include <stdio.h> int main( ){ printf("5! = %ld\n", factorial(5)); } C語言版本 N階乘就是N乘以N-1階乘
GCD -- 歐幾里得的最大公約數 • 輾轉相除法 (recursive概念!) GCD(m, n) = GCD(n, m%n) 但如果 n 是 0 則答案為 m long gcd(long m, long n) { if(n==0) return m; return gcd(n, m%n); } 如何寫成non-recursive version ?
GCD non-recursive version long gcd(long m, long n) { int r; /* remainder */ while(n != 0) { r = m%n; m = n; n = r; } return m; }
Recursive 也可以很有趣(1/3) Fibonacci Series: (費氏數列) 一開始有一對兔子 小兔子隔一個月可以長大為成兔 每對成兔每隔一個月可生出一對兔子 假設兔子永遠不死, 問第 n 個月時有幾對兔子 ? 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, . fib(n) 0 1 2 3 4 5 6 7 8 9 10 11 = n
Recursive 也可以很有趣(2/3) long fib(int n) { if( n < 0) return 0; if( n ==1 || n==0) return 1; return fib(n-1)+fib(n-2); } /*給我 n 我就告訴你第 n 個月時有幾對兔子 */ /*第n個月兔子數=第 n-1 個月兔子+第 n-2 個月兔子*/ /*但是, 最開始兩個月例外 ! */
Recursive 也可以很有趣(3/3) Fibonacci Series(費氏數列): 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, … 34/55 = 55/89 = 89/144 = 0.618 黃金分割比:) 神奇的費氏數列: 任何事物接近這些數字會有變化 請看 . .可怕的 巧合: !? 三 重 魔 力 . . . 民國 34 年台灣光復, 民國89年變天 國民黨從日本手上搶回台灣執政剛好55 年!
問題與思考 (Recursion) • 寫出 non-recursive版的Fibonacci function ? • 考慮小兔子隔兩個月可以長大為成兔 ? • 考慮成兔的懷孕期是兩個月 ? • 其他 Recursive 問題 • Recursive 版的 binary search • Quick sort • Hanoi tower problem • …
Factorial – cache ans in a Table • public class Factorial3 { • //create an array to cache values 0! Through 20! • static long[ ] table = new long[21]; • static {ans[0] = 1;} //factorial of 0 is 1 • static int last = 0; • public static long factorial(int n) { • if(n <= last) return ans[n]; • long tmp = ans[last]; int k = last; • while (k < n) { • tmp = (k+1) * tmp; /* (k+1) ! */ • if(last < 20) {++last; ans [last ] = tmp;} • ++k; • } /* while */ • return tmp; • } • } Cache 唸作 cash
Computing Primes (1/3) • Finding the largest prime number smaller than a specified integer: • Input integer m, find p m such that p is a prime and if there is prime p’ > p then p’ must be larger than m. • Finding all prime numbers that smaller than a specified integer? 1 4 6 8 9 10 12 14 15 16 18 20 2 3 5 7 11 13 17 19
2 2 3 3 4 4 Computing Primes (2/3) • Algorithm • main idea: find primes by eliminating multiples of the form k j, where j is a prime smaller than square-root(m) and k is an integer such that k j m. 2 i j square-root(m) ... ... prime j i 2 2 3 2 i j j 4 2 i ... ... ...
Computing Primes (3/3) • Finding all prime numbers that smaller than a specified integer? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Example: Find Primes (1/2) • Import java.lang.*; • public class Sieve { • public static void main(String[] args) { • int max = 100; //Assign a default value • try {max = Integer.parseInt(arg[0]);} • catch (Exception e) {} //Silently ignore exceptions. • //Create an array that specifies whether each number is prime or not. • Boolean[] isprime = new boolean[max+1]; • //Assume that all numbers are primes, until proven otherwise. • for (int i = 0; <= max; i++) isprime[i] = true; • //We know that that 0 and 1 are not prime. Make a note of it. • isprime[0] = isprime[1] = false;
Example: Find Primes (2/2) • //To compute all primes less than max, we need to rule out multiples of all • //integers less than the square root of max. • int n = (int) Math.ceil(Math.sqrt(max)); • for (int i = 0; i <= n; i++) { • if (isprime[i]) { int k = 2; • for (int j = k*i; j <= max; j = (k ++)*i) • isprime[j] = false; } • } • int largest; • for (largest = max; !sprime[largest]; largest--); //empty loop body • System.out.println("The largest prime less than or equal to " + max + " is " • + largest); • } • }
Sorting Numbers • Sorting: • Input n numbers, sort them such that the numbers are ordered increasingly. • 3 9 1 6 5 4 8 2 10 7 • 1 2 3 4 5 6 7 8 9 10
Selection Sort (1/4) • A simple sorting algorithm • Purpose: • Input: an array A containing n integers. • Output: sorted array. • 1. i := 2; • 2. Find the least element a from A(i) to A(n); • 3. If a is less than A(i - 1), exchange A(i - 1) and a; • 4. i := i + 1; if (i <= n) goto step (2).
Selection Sort (2/4) • 1st step: 3 9 1 6 5 4 8 2 10 7 • 2nd step: 1 9 3 6 5 4 8 2 10 7 • 1 2 3 6 5 4 8 9 10 7 • … ... swap swap
Selection Sort (3/4) • Sorting program: • public class SelSort { • public static void sort(double[ ] nums) { • for(int i = 0; i < nums.length; i++) { • int min = i +1; • for (int j = i+2; j < nums.length; j++) { • if (nums[j] < nums[min]) min = j; • } • if (nums[i] > nums[min]) { • double tmp; • tmp = nums[i]; nums[i] = nums[min]; nums[min] = tmp; • } • } • } • }
Selection Sort (4/4) • In separate file: • public class SortNumber { • public static void main (String[ ] args) { • double[ ] nums = new double[10]; //Create an array to hold numbers • for(int i = 0; i < nums.length; i++) //Generate random numbers • nums[i] = Math.random( )*100; • SelSort.sort(nums); //Sort them • for (int j = 0; j < nums.length; j++) //Print them out • System.out.println(nums [j] ); • } • } Math.random( ) : see next slide
Insertion Sort • public class InsSort { • public static void sort(double[ ] nums) { • for(int i = 1; i < nums.length; i++) { • double tmp = nums[i]; /* we want to put this in proper position */ • k = i – 1; • while ((k>=0) && nums[k] > tmp ) { /* smaller than me */ nums[k+1] = nums[k]); /* move it down */ • --k; • } • nums[k+1] = tmp; /* copy it into correct position */ • } • } • }
Test the Insertion Sort • In separate file as previous example (Selection sort): • public class SortNumber { • public static void main (String[ ] args) { • double[ ] nums = new double[10]; //Create an array to hold numbers • for(int i = 0; i < nums.length; i++) //Generate random numbers • nums[i] = Math.random( )*100; • InsSort.sort(nums); //Sort them using insertion sort • for (int j = 0; j < nums.length; j++) //Print them out • System.out.println(nums [j] ); • } • }
Bubble Sort • public class BubSort { • public static void sort(double[ ] nums) { • for(int i = nums.length-2; i >=0; --i) { • int flag = 0; /* Assume no exchange */ • for(k=0; k <= i; ++k) { /* walk through all every pass */ • if ( nums[k] > nums[k+1] ) { /* incorrect order */ • double tmp=nums[k]; nums[k]=nums[k+1]; nums[k+1]=tmp; • ++flag; • } • } • if(flag == 0) break; /* no need to do next pass */ • } • } • }
Quick Sort (1/6) • Algorithm quick_sort(array A, from, to) • Input: from - pointer to the starting position of array A • to - pointer to the end position of array A • Output: sorted array: A’ • 1. Choose any one element as the pivot; • 2. Find the first element a = A[i] larger than or equal to pivot from • A[from] to A[to]; • 3. Find the first element b = A[j] smaller than or equal to pivot from • A[to] to A[from]; • 4. If i < j then exchange a and b; • 5. Repeat step from 2 to 4 until j <= i; • 6. If from < j then recursive call quick_sort(A, from, j); • 7. If i < to then recursive call quick_sort(A, i, to);
Choose 5 as pivot Quick Sort (2/6) • Quick sort • main idea: • 1st step: 3 1 6 5 4 8 10 7 • 2nd step: 3 2 1 5 8 9 10 7 • 3rd step: 3 2 1 4 5 6 8 9 10 7 from to 9 2 j i 6 4 Smaller than any integer right to 5 greater than any integer left to 5
pivot Quick Sort (3/6) to from • Quick sort • 4th step: 2 4 5 6 10 9 • 5th step: 1 2 3 4 5 pivot from to 1 3 8 7 6th step: 5 6 7 8 10 9 7th step: 7 8 10 9 8th step: 9 10
Quick Sort (4/6) • public class QuickSorter { • public static void sort (int[ ] a, int from, int to) { • if ((a == null) || (a.length < 2)) return; • int i = from, j = to; • int pivot = a[(from + to)/2]; • do { • while ((i < to) && (a[i] < pivot)) i++; • while ((j > from) && (a[j] >= pivot)) j--; • if (i < j) { int tmp =a[i]; a [i] = a[j]; a[j] = tmp;} • i++; j--; • }while (i <= j); • if (from < j) sort(a, from, j); • if (i < to) sort(a, i, to); } • }
Quick Sort (5/6) 3, 4, 6, 1, 10, 9, 5, 20, 19, 14, 12, 2, 15, 21, 13, 18, 17, 8, 16, 1 1, 12, 2, 15, 21, 13, 18, 17, 8, 16, 3, 4, 6, 1, 10, 9, 5, 20, 19, 14 j i 8, 14 1, 12, 2, 15, 21, 13, 18, 17, ,16, 19, 3, 4, 6, 1, 10, 9, 5, 20, i j 3, 4, 6, 1, 10, 9, 5, 8, 13 , 1, 12, 2,15, 21, 19, 18, 17, 20, 16, 14 i j 3, 4, 6, 1, 10, 9, 5, 8, 13, 1, 12, 2, 14, 21, 19, 18, 17, 20, 16, 15 14 i 3, 4, 6, 1, 10, 9, 5, 8, 13, 1, 12, 2 j
Quick Sort (6/6) • public class BQSorter { • public static void sort (int[ ] a, int from, int to) { • if ((a == null) || (a.length < 2) || from >= to) return; • int k = (from + to)/2; int tmp =a[to]; a [to] = a[k]; a[k] = tmp; • int pivot = a[to]; int i = from, j = to-1; • while(i < j ) { • while ((i < j) && (a[i] < pivot)) i++; • while ((i < j) && (a[j] >= pivot)) j--; • if (i < j) { tmp =a[i]; a [i] = a[j]; a[j] = tmp;} • }; • tmp =a[i]; a [i] = a[to]; a[to] = tmp; • if (from < i-1) sort(a, from, i-1); • if (i < to) sort(a, i+1, to); } • }
Merge Sort (1/3) • Merging means the combination of two or more ordered sequence into • a single sequence. For example, can merge two sequences: 503, 703, 765 • and 087, 512, 677 to obtain a sequence: 087, 503, 512, 677, 703, 765. • A simple way to accomplish this is to compare the two smallest items, • output the smallest, and then repeat the same process. 503 703 765 087 512 677 503 703 765 512 677 087 703 765 512 677 087 503
Merge Sort (2/3) • Algorithm Merge(s1, s2) • Input: two sequences: s1 - x1 x2 ... xm and s2 - y1 y2 ... yn • Output: a sorted sequence: z1 z2 ... zm+n. • 1.[initialize] i := 1, j := 1, k := 1; • 2.[find smaller] if xi yjgoto step 3, otherwise goto step 5; • 3.[output xi] zk.:= xi, k := k+1, i := i+1. If i m, goto step 2; • 4.[transmit yj ... yn] zk, ..., zm+n := yj, ..., yn. Terminate the algorithm; • 5.[output yj] zk.:= yj, k := k+1, j := j+1. If j n, goto step 2; • 6.[transmit xi ... xm] zk, ..., zm+n := xi, ..., xm. Terminate the algorithm;
Merge Sort (3/3) • Algorithm Merge-sorting(s) • Input: a sequences s = < x1, ..., xm> • Output: a sorted sequence. • 1. If |s| = 1, then return s; • 2. k := m/2; • 3. s1 := Merge-sorting(x1, ..., xk); • 4. s2 := Merge-sorting(xk+1, ..., xm); • 5. return(Merge(s1, s2));
Time complexity of Mergesort • Takes roughly n·log2n comparisons. • Without the shortcut, there is no best or worst case. • With the optional shortcut, the best case is when the array is already sorted: takes only (n-1) comparisons.
Binary Search (1/5) • Works for an array of numbers or objects that can be compared and are arranged in ascending (or descending) order. • A very fast method: only 20 comparisons are needed for an array of 1,000,000 elements; (30 comparisons can handle 1,000,000,000 elements; etc.)
Binary Search (2/5) • Main idea: “divide and conquer”: • compare the target value to the middle element; • if equal, all set • if smaller, apply binary search to the left half; • if larger, apply binary search to the right half. NJ v ... MI MN MO MS MT NC ND ... NJ ... MI MN MO MS MT NC ND ...
Binary Search (3/5) • Recursive implementation: public int binarySearch (int arr [ ], int value, int left, int right) { int middle = (left + right) / 2; if (value == arr [middle] ) return middle; else if ( value < arr[middle] && left < middle ) return binarySearch (arr, value, left, middle - 1); else if ( value > arr[middle] && middle < right ) return binarySearch (arr, value, middle + 1, right ); else return -1; // Not found }
Binary Search (4/5) • Iterative implementation: public int binarySearch (int arr [ ], int value, int left, int right) { while (left <= right) { int middle = (left + right) / 2; if ( value == arr [middle] ) return middle; else if ( value < arr[middle] ) right = middle - 1; else /* if ( value > arr[middle] ) */ left = middle + 1; } return -1; // Not found }
Binary Search (5/5) • The average number of comparisons is roughly log2n • The worst-case is log2 (n + 1) rounded up to an integer (e.g. 2 for n = 3, 3 for n = 7, 4 for n = 15, etc.)
PRNG • Pseudo Random Number Generator • java.lang.Math.random( ) • A real (double) number: Uniform random number [0, 1) • java.util.Random • A utility class in java.util package • Has many miscellaneous random # generating functions • java.lang.Math.random( ) actually uses nextDouble( ) in this class • nextInt( ) returns a number like int rand( ) in C language • nextGaussian( ) returns a # in standard Normal distribution
java.util.Random (1/2) • Benchmarks uses the java.util.Random class — a more controlled way to generate random numbers. • Constructors: • If we set the same “seed,” we get the same“random” sequence. Default “seed”: System.currentTimeMillis() Random generator = new Random(); Random generator2 = new Random(seed); long seed;
java.util.Random (2/2) • Methods: All 232 possible int values are produced with (approximately) equal probability int k = generator.nextInt (); int k = generator.nextInt (n); double x = generator.nextDouble (); 0 k < n 0 x < 1
java.util.Arrays • Provides static methods for dealing with arrays. • Works for arrays of numbers, Strings, (and “comparable”Objects). • Methods: int pos = Arrays.binarySearch (arr, target); Arrays.sort (arr); Arrays.sort (arr, from, to); Arrays.fill (arr, value); // fills arr with a given value Arrays.fill (arr, from, to, value);
java.util.ListInterface • The List library interface describes a list of objects in abstract terms • In a list, objects are arranged in sequence obj0, obj1, ..., objn-1 • In Java, a list holds references to objects • A list can contain duplicate objects (both obj1.equals(obj2) and obj1 == obj2 )
List Methods (a Subset) • int size(); • boolean isEmpty (); • boolean add (Object obj); • void add (int i, Object obj); • Object set(int i, Object obj); • Object get(int i); • Object remove(int i); • boolean contains(Object obj); • int indexOf(Object obj); returns true inserts obj as the i-th value; i must be from 0 to size() i must be from 0 to size() -1 use equals to compare objects
java.util.ArrayList (1/6) • Implements List using an array • Keeps track of the list capacity (the length of the allocated array) and list size (the number of elements currently in the list) capacity size "Cat" "Hat" "Bat"