430 likes | 580 Views
Arrays: Matrix Renamed. Instructor: Mainak Chaudhuri mainakc@cse.iitk.ac.in. Arrays. Till now we are able to declare and initialize few variables Reality: need to compute on a large amount of data Arrays are data structures that can hold a series of values Just a new name for matrix
E N D
Arrays: Matrix Renamed Instructor: Mainak Chaudhuri mainakc@cse.iitk.ac.in
Arrays • Till now we are able to declare and initialize few variables • Reality: need to compute on a large amount of data • Arrays are data structures that can hold a series of values • Just a new name for matrix • Just like a matrix index, an array uses an index to access a particular value
Initializing an array int justAVector[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; String myFriendsNames[] = {“John”, “Brian”, “Jill”, “Jack”, “Ivan”}; char firstFewDigits[] = {‘0’, ‘1’, ‘2’, ‘3’}; boolean whichOfMyFriendsAreTall[] = {false, false, true, true, false}; • Size of an array array_name.length
Finding average class Average { public static void main (String arg[]) { double dailyRainFall[] = {12.3, 13.5, 4.2, 2.4, 1.1, 0, 10.8}; int i; float average = 0; for (i=0; i<7; i++) { average += dailyRainFall[i]; } average /= 7; System.out.println (“Average rain fall: ” + average + “ mm”); } }
Finding maximum class Maximum { public static void main (String arg[]) { int n = 100; double numbers[] = new double[n]; Initialize (numbers, n); System.out.println (“Maximum: ” + FindMax (numbers, n)); }
Finding maximum public static void Initialize (double numbers[], int length) { int i; for (i=0; i<length; i++) { numbers[i] = Math.sin(2*Math.PI/(i+1)) + Math.cos(2*Math.PI/(i+2)); } }
Finding maximum public static double FindMax (double numbers[], int length) { double max = numbers[0]; int i; for (i=1; i<length; i++) { if (numbers[i] > max) { max = numbers[i]; } } return max; } } // end class
Finding maximum • Want to print the position of the maximum also • Need to return two values from FindMax • Use a 2-element array as return type • Shows why returning local reference does not work • Shows the distinction between two different memory areas: stack and heap
Finding max and max index class Maximum { public static void main (String arg[]) { int n = 100; double numbers[] = new double[n]; double result[]; Initialize (numbers, n); result = FindMax (numbers, n); // Danger! System.out.println ("Maximum: " + result[0] + ", Position: " + (int)result[1]); }
Finding max and max index public static void Initialize (double numbers[], int length) { int i; for (i=0; i<length; i++) { numbers[i] = Math.sin(2*Math.PI/(i+1)) + Math.cos(2*Math.PI/(i+2)); } }
Finding max and max index public static double[] FindMax (double numbers[], int length) { // Does not work double result[] = {numbers[0], 0}; int i; for (i=1; i<length; i++) { if (numbers[i] > result[0]) { result[0] = numbers[i]; result[1] = i; } } return result; // Local reference on stack } } // end class
Finding max and max index public static double[] FindMax (double numbers[], int length) { // This one works double result[] = new double[2]; // On heap result[0] = numbers[0]; result[1] = 0; int i; for (i=1; i<length; i++) { if (numbers[i] > result[0]) { result[0] = numbers[i]; result[1] = i; } } return result; // Reference on heap } } // end class
Array layout in memory • Recall that every variable requires some space to be stored in memory • Often the compiler is responsible for allocating this space • In other words, every variable has an address (just like you and I have addresses) • The address is often called a reference of a variable in Java • If I try to print the value at this address, I will get the value of the variable • How is an array stored in memory?
Array layout in memory • The array elements are stored contiguously in memory • numbers[0], numbers[1], … • Starting address is numbers (same as the address of numbers[0]), add 8 to get the address of numbers[1] • doubles are 64 bits in size and memory is always byte addressed (one byte is 8 bits) • Putting array names in method arguments is equivalent to passing the arrays by reference: modifications to arrays inside the method are reflected outside the method • Of course, it is possible to pass individual array elements (not by reference, but by value i.e. as private copies)
FindMax: reference as a value class Maximum { // Still pass by value public static void main (String arg[]) { int n = 100; double numbers[] = new double[n]; double result[] = new double[2]; Initialize (numbers, n); result[0] = numbers[0]; result[1] = 0; FindMax (numbers, n, result); // reference System.out.println ("Maximum: " + result[0] + ", Position: " + (int)result[1]); }
FindMax: reference as a value public static void Initialize (double numbers[], int length) { int i; for (i=0; i<length; i++) { numbers[i] = Math.sin(2*Math.PI/(i+1)) + Math.cos(2*Math.PI/(i+2)); } }
FindMax: reference as a value public static void FindMax (double numbers[], int length, double r[]) { int i; for (i=1; i<length; i++) { if (numbers[i] > r[0]) { r[0] = numbers[i]; r[1] = i; } } } } // end class
FindMax: passing values class Maximum { // This example does not work public static void main (String arg[]) { int n = 100; double numbers[] = new double[n]; double result[] = new double[2]; Initialize (numbers, n); result[0] = numbers[0]; result[1] = 0; FindMax (numbers, n, result[0], result[1]); System.out.println ("Maximum: " + result[0] + ", Position: " + (int)result[1]); }
FindMax: passing values public static void Initialize (double numbers[], int length) { int i; for (i=0; i<length; i++) { numbers[i] = Math.sin(2*Math.PI/(i+1)) + Math.cos(2*Math.PI/(i+2)); } }
FindMax: passing values public static void FindMax (double numbers[], int length, double max, double position) { int i; for (i=1; i<length; i++) { if (numbers[i] > max) { max = numbers[i]; position = i; } } } } // end class
Always pass by value • Java always passes arguments by value • References are just a special kind of values • Modifying a value in a method does not have any effect on the caller • Modifying a value pointed to by a reference in a method does change the value in the caller also • References are addresses and hence a modification of the contents at the address will have “global” visibility • On the other hand, argument values are just copied in the “local memory” of a method; so a modification to a value within a method always remains local (changes contents of local memory)
Reversing an array class Reverse { public static void main (String arg[]) { int size = 10; int somethingStrange[] = new int[size]; Initialize (somethingStrange, size); PrintArray (somethingStrange, size); Reverse (somethingStrange, size); PrintArray (somethingStrange, size); }
Reversing an array public static void Initialize (int array[], int size) { int i; array[0] = 1; for (i=1; i<size; i++) { array[i] = (array[i-1]*3) % 23; } }
Reversing an array public static void Reverse (int array[], int size) { int head = 0, tail = size-1; while (head < tail) { Swap (array, head, tail); head++; tail--; } }
Reversing an array public static void Swap (int array[], int i, int j) { int temp; temp = array[i]; array[i] = array[j]; array[j] = temp; }
Reversing an array public static void PrintArray (int array[], int size) { int i; for (i=0;i<size;i++) { System.out.println (array[i]); } } } // end class
Bubble sort class BubbleSort { public static void main (String arg[]) { int size = 20; double array[] = new double[size]; Initialize (array, size); // not shown PrintArray (array, size); // not shown Sort (array, size); PrintArray (array, size); // not shown }
Bubble sort public static void Sort (double array[], int size) { int i, j; for (i=1;i<=size-1;i++) { for (j=0;j<=size-2;j++) { // better: j<=size-i-1 CompareAndSwap (array, j, j+1); } // Invariant: maximum of sub-array is // in position size-i } }
Bubble sort public static void CompareAndSwap (double array[], int p, int q) { double temp; if (array[p] > array[q]) { temp = array[p]; array[p] = array[q]; array[q] = temp; } } } // end class (How many comparisons?)
Insertion sort public static void Sort (double array[], int size) { int i, j; for (i=1; i<size; i++) { for (j=0; array[i] > array[j]; j++); if (j < i) { Insert (array, i, j); } // Invariant: the first i+1 element // are sorted }
Insertion sort public static void Insert (double array[], int oldpos, int newpos) { int i; double candidate = array[oldpos]; for (i=oldpos-1; i>=newpos; i--) { array[i+1] = array[i]; } array[i+1] = candidate; }
Insertion sort • How many comparisons? • Need to consider worst case • What does the array look like in the worst case? • What is the best case? • Just the number of comparisons does not tell you the whole story • How many assignments do you execute?
Merging two sorted arrays • Suppose we have sorted the first m and the remaining n-m elements of an array separately • We need to merge these two sorted halves to get a complete sorted array • Assume that everything is sorted in ascending order
Merging two sorted arrays public static void Merge (double array[], int start, int m, int n) { // start would be 0 in this case double temp[] = new double[n-start]; int index = 0, index1, index2, i; for (index1=start, index2=m; (index1 < m) && (index2 < n);) { if (array[index1] < array[index2]) { temp[index] = array[index1]; index++; index1++; } else { temp[index] = array[index2]; index++; index2++; } } // continued in next slide
Merging two sorted arrays for(;index1<m;index1++,index++) { temp[index] = array[index1]; } for(;index2<n;index2++,index++) { temp[index] = array[index2]; } for (i=start;i<n;i++) { array[i] = temp[i-start]; } }
Merge sort • Recursively sort half of the array separately and merge them class MergeSort { public static void main (String arg[]) { int n = 20; double array[] = new double[n]; Initialize (array, n); // not shown Sort (array, 0, n-1); } // continued in next slide
Merge sort public static void Sort (double array[], int start, int end) { if (start < end) { Sort (array, start, start+(end+1-start)/2-1); Sort (array, start+(end+1-start)/2, end); Merge (array, start, start+(end+1-start)/2, end+1); } } } // end class
Merge sort • Running time? Let it be T(n) for an array of size n T(n) = 2T(n/2) + cn for some constant c • Solution to this functional equation (or recurrence) is the running time of merge sort • T(n) = c’nlog2(n) for some constant c’ and large n • I can absorb the base of log in the constant • Note that this is the worst case running time of merge sort • Much better than bubble sort and insertion sort which had worst case running time quadratic in n
Prime numbers • Previously we checked for primality of an integer n by dividing it by all integers up to √n • We only need to divide by the primes up to √n • Use an array to remember the primes seen so far
Prime numbers class PrimeNumbers { // Find all primes up to n public static void main (String arg[]) { int n = 10000; // Assume n > 1 // Use Dusart’s bound (just using n wastes // too much of memory for large n) int maxNumPrimes = (int)((n/Math.log(n))*(1+1.2762/Math.log(n))); int primes[] = new int[maxNumPrimes]; int numPrimesFound = 0; int i; // continued on next slide
Prime numbers for (i=2; i<=n; i++) { if (CheckPrimality (i, primes, numPrimesFound)) { primes[numPrimesFound] = i; numPrimesFound++; } } PrintPrimes(primes, numPrimesFound); } // end main // continued on next slide
Prime numbers public static boolean CheckPrimality (int n, int primes[], int count) { int i; for (i=0; (i<count) && (primes[i] <= Math.sqrt(n)); i++) { if ((n%primes[i])==0) { return false; } } return true; } // continued on next slide
Prime numbers public static void PrintPrimes (int primes[], int count) { int i, j=0; for (i=0; i<count; i++) { System.out.print (primes[i] + “ ”); j++; if (j==10) { // print 10 primes per line System.out.print (“\n”); j=0; } } System.out.print (“\n”); } } // end class