csc 1051 algorithms & data structures ii
TRANSCRIPT
CSC 1052 Algorithms & Data Structures II
Program Organization, Encapsulation and Algorithm Efficiency
2
PROGRAM ORGANIZATION
The package Statement
A package is a group of related classes
Examples in the Java API:
java.util
java.io.exceptions
In a program, you can refer to a class by its fully qualified name, such as java.util.Scanner
Or you can import a class and use the class name alone (Scanner)
3
import java.util.Scanner;
The package Statement
A package statement is used to put your own class into a package
It must be the first statement in the file that defines the class
4
package com.rephactor.utils;
public class ArrayUtilities{
// whatever}
If you don't explicitly put a class into a package, it is consideredpart of the default package
The package Statement
A package name is made up of one or more identifiers separated by periods
Not only does a package form a logical grouping of classes, it also creates a name space
Two classes can have the same name as long as they're in different packages
java.util.Timerjavax.swing.Timer
By organizing classes into packages, you don't have to worry about using a name that another developer has chosen
5
The package Statement
Of course, package names must be unique
Convention: construct package names by reversing an appropriate domain name (which are guaranteed unique)
For example, packages created by the company that owns rephactor.com might begin with com.rephactor
So they might have packages such as
com.rephactor.utilscom.rephactor.topics
6
The package Statement
For example, the ArrayUtilities class must be in a subdirectory com/rephactor/utils relative to the program or classpath
7
The import Statement
Classes in the Java API is part of a particular packageString is in the java.lang packageRandom is in the java.util package
A package is a group of related classes
A class can always be referred to by its fully qualified name
java.util.Random
Package organization allows two classes to have the same name, such as
java.util.Timer and java.awt.Timer
8
The import Statement
9
Random gen = new Random();
Using the fully qualified name is not always convenient:
An alternative is to import the class
Import statements go above the class that uses them
import java.util.Random;
Then the simple name can be used throughout the program:
java.util.Random gen = new java.util.Random();
The import Statement
10
import java.util.*;
Classes from the java.lang package are automatically imported
That's why we don't import classes like System or String
If you're going to use multiple classes from a package, you can use the * wildcard character:
Javadoc
11
Javadoc comments provide information about program elements, such as classes and methods.
They make it possible for the Java compiler to automatically generate documentation on commented code. This is where the online Java API documentation comes from.
It is recommended that every class and method be described using Javadoc comments. In practice, though, this isn't always done.
Javadoc
12
/*** This class contains methods that compute* various values related to circles.** @author Rephactor Java* @version 1.0*/public class CircleStats{
...
A Javadoc comment begins with the characters /** and ends with the characters */. Here is a class comment:
Javadoc
13
/*** This class contains methods that compute* various values related to circles.** @author Rephactor Java* @version 1.0*/public class CircleStats{
...
A Javadoc comment begins with the characters /** and ends with the characters */. Here is a class comment:
Javadoc
14
There are numerous Javadoc tags that can be used that will be parsed into meaning API documentation. Here are some of the more popular:
@author Identifies the programmer@param Describes a method or constructor parameter@return Describes the return value of a method@throws Indicates a method may throw an exception@version Indicates version of the code, a number or date
ENCAPSULATION
Encapsulation
Encapsulation is the principle that a class should protect its data from unnecessary accessThis is about good design – creating software using elements that have limited, controlled interaction with other elementsIf an object is encapsulated, problems are localized and easier to find and fixCode that interacts with an object is a client of that objectEncapsulation ensures that a client cannot "reach in" and change the values of instance variables directly
16
Encapsulation
From the client's point of view, an object should be a black boxThe client doesn't need to know exactly what data is managed by an object or how it's organized
17
Instead, the client interacts with an object through its publicinterface – the set of methods a client can call
Encapsulation
There are actually four access levels in Java – protected access relates to inheritance
If no access modifier is used, the variable or method has default access (or package access)
18
ModifierAccessible within itsclass
Accessible from any class in the same package
Accessible from any subclass
Accessible from any classes in other packages
public Yes Yes Yes Yes
protected Yes Yes Yes No
default Yes Yes No No
private Yes No No No
Encapsulation
An accessor method is a method that provides the client with the value of an instance variable
Some accessor methods take the form getX, where X is the attribute – this is also called a "getter" method
19
public double getBalance(){
return balance;}
Encapsulation
Methods that modify instance data are mutator methods
They might be classic "setters"
20
public void setName(String newName){
name = newName;}
Unconditional mutators are almost as bad as public variables,but at least they are explicitly defined as such
The deposit and withdraw methods of a bank account aremutators because they change the balance
Some methods are both accessors and mutators
2D ARRAYS & METHOD OVERLOADING
Two-Dimensional Arrays
A basic array is a single-dimensional array
A two-dimensional array is accessed via row and column and appropriate for tabular data
22
Movie Rev 1 Rev 2 Rev 3 Rev 4 Rev 5
Godzilla 3 3 4 2 3
Guardians of the Galaxy 4 4 5 5 4
Jersey Boys 3 3 3 4 3
Maleficent 4 3 3 4 3
The Expendables 3 2 1 3 2 2
The Fault in our Stars 4 3 4 4 3
X-Men: Days of Future Past 4 3 4 3 3
Two-Dimensional Arrays
Both row and column indexes begin at 0
Use brackets for each index
23
Two-Dimensional Arrays
All elements must have the same type
The type of a 2-D array of integers is int[][]
24
As with a 1-D array, the size of each dimension is specified whenthe array object is created
int[][] matrix;
matrix = new int[12][20];
This array has 12 rows (indexed 0 to 11) and 20 columns(indexed 0 to 19)
Two-Dimensional Arrays
You can also use an initialization list to create 2-D arrays
25
This is essentially a list of lists
int[][] reviews = { {3, 3, 4, 2, 3},{4, 3, 4, 3, 3},{3, 3, 3, 4, 3},{4, 3, 3, 4, 3},{2, 1, 3, 2, 2},{4, 3, 4, 4, 3},{4, 4, 5, 5, 4} };
Two-Dimensional Arrays
Nested loops are often used to access elements in a 2-D array
The following code fills a 2-D array with random double values
26
double[][] scores = new double[30][5];
for (int row = 0; row < scores.length; row++)for (int col = 0; col < scores[row].length; col++)
scores[row][col] = Math.random() * 100;
scores.length is the number of rows
scores[row].length is the number of columns in that row
Two-Dimensional Arrays
In Java, a 2-D array is really an array of arrays
If values is a 2-D array with 5 rows and 7 columns, it could be depicted like this:
27
Two-Dimensional Arrays
The concept of a 2-D array can be generalized into a multidimensional array
28
int[][][] accidents = new int[12][31][24];
This array might be used to store the number of traffic accidentsin a town, organized by month, day, and hour
Method Overloading
Method overloading is a technique in which two or more methods in a class can have the same nameThe compiler must be able to figure out which method is being called by analyzing the parameter listA method signature is the name of the method along with the types of its parametersAll method signatures in a class must be uniqueThat means the names can be the same as long as the number, types, and order of the parameters are distinct
29
Method Overloading
For example:
30
public void setCoordinates(int x, int y){
// whatever}
public void setCoordinates(Point p){
// whatever}
The signatures for these methods aresetCoordinates(int, int)setCoordinates(Point)
Method Overloading
Suppose the following invocation is made:
31
target.setCoordinates(13, 58);
The compiler would map this invocation to the version of the method that takes two int parameters
Method overloading is appropriate in situations where the same operation is being applied to different data
Constructors are often overloaded
Method Overloading
Another example:
32
public static int add(int i, int j){
return i + j;}
public static double add(double i, double j){
return i + j;}
public static double add(double i, double j, double k){
return i + j + k;}
Method Overloading
The signatures of those methods areadd(int, int)add(double, double)add(double, double, double)
The compiler looks for the most specific match it can find
If two or more methods are equally appropriate, the compiler will issue an error (ambiguous invocation)
The return type is NOT part of the method signature
Overloaded methods cannot differ only by their return type
33
Method Overloading
The print and println methods are overloaded several timesEach version takes a single type as a parameter
println(int)println(double)println(String)
etc.So the following two calls invoke different methods
34
System.out.println("Hello there!");System.out.println(total);
ALGORITHM EFFICIENCY
Efficiency and Big O Notation
An efficient algorithm solves a problem with minimal waste of resources, particularly CPU time
Efficiency can be measured various ways
Measuring the actual execution time on a particular machine doesn't tell us much about the solution in general
Benchmark scenarios provide a better picture, but are still a function of particular hardware and input data
36
Efficiency and Big O Notation
Consider a linear search – finding a target element in a list of n elements
best case – target is first element in the list
worst case – target is last element, or not in the list at all
average case – makes n/2 comparisons
Algorithm analysis is the discipline within computer science that studies efficiency
37
Efficiency and Big O Notation
An algorithm's time complexity is a function that expresses time in terms of n, the amount of input data
Consider two algorithms that sort a list of n values
38
Efficiency and Big O Notation
For both algorithms, the time increases as the input size increasesWhat matters is the growth rate of the time complexity function
What is the shape of the curve?How quickly does it increase (how steep is it)?
Instead of focusing on how fast an algorithm runs, we focus on how well the solution scales as n gets biggerThe time it takes Algorithm A to solve the problem grows much more quickly than Algorithm B, so we conclude that B is better
39
Efficiency and Big O Notation
Now suppose the time complexity of a particular algorithm is
40
We could plot this curve and compare it to other timing functions
However, we don't care about the exact function, we care abouthow quickly it grows
The n2 term dictates the shape of this curve far more than any ofthe other terms
This is the dominant term of the function
Efficiency and Big O Notation
Compare various values of n and n2
41
n n2
2 4
10 100
50 2,500
100 10,000
1,000 1,000,000
5,000 25,000,000
Compared to n2, the n term becomes irrelevant as n growsCoefficients of the terms are irrelevant as well
Efficiency and Big O Notation
Big O notation is used to simplify the discussion of efficiencyIt eliminates the irrelevant details
42
Big O Category Name
O(1) Constant
O(log n) Logarithmic
O(n) Linear
O(n log n) Log-Linear
O(n2) Quadratic
O(2n) Exponential
The Big O category is based on the dominant term, and therefore the growth rate, of the time complexity function
Example: O(n)
You say:
"Order n"
Efficiency and Big O Notation
Therefore, this timing function is a member of the quadratic class of algorithms
43
Big O categories can be thought of as defining the order ofmagnitude of an algorithmAny two algorithms in the same Big O category are generallyequal in terms of efficiency
Efficiency and Big O Notation
Comparing Big O terms for small n:
44
Efficiency and Big O Notation
For larger n:
45
Efficiency and Big O Notation
The ordering of the Big O categories is clear:O(1) < O(log n) < O(n) < O(n log n) < O(n2) < O(2n)
Algorithms with O(1) complexity are independent of the size of the input
Example: Finding the first element in a listLogarithms are almost always base 2 for computer problems, though that is largely irrelevant in terms of Big O analysisIf a problem cannot be solved in a reasonable amount of for a moderate value of n, it is said to be intractable
46
Loop Analysis
The time complexity of an algorithm is a function that describes how long it takes to execute relative to it's input size (n)
Big O notation allows us to categorize time complexity functions by their dominant term
We're concerned about the growth rate (shape) of the curve as N increases
Let's examine a series of code fragments that use loops to determine their Big O complexity
47
Loop Analysis
The following loop executes n times:
48
The loop body takes a constant time (call it c) to executeSo it's time complexity can be expressed as follows:
for (int i = 1; i <= n; i++)sum = sum + i;
This loop has linear complexityThe time it takes to execute grows in direct proportion to theinput size n
Loop Analysis
This loop executes exactly 20 times:
49
Therefore, the entire loop has constant complexity
for (int i = 1; i <= 20; i++)sum = sum + i;
The loop is not a function of n (the input size)If the literal 1000 was used (instead of 20), it would still beconstant complexity
Loop Analysis
The amount of code in the loop body is not the issue
50
for (i = 1; i <= n; i++){
sum = sum + i;System.out.println(i);if (sum > 50)
sum = 0;else
sum = sum * 2;}
Each part of this loop body contributes constant time
Loop Analysis
Suppose k is calculated to be log2n
51
The loop executes log2n times, so:
for (int i = 1; i <= k; i++)System.out.println(i);
Even though n is not used explicitly, the number of executionsis still a function of nIn Big O analysis, the logarithm base doesn't matter: O(log n)equals O(logan) for any base a
Loop Analysis
Now consider a nested loop:
52
The outer loop executes n timesFor each iteration of the outer loop, the inner loop executesn times
for (i = 1; i <= n; i++)for (j = 1; j <= n; j++)
System.out.println(i + j);
So this code has quadratic complexityIf the input size doubles, the execution time quadruples
Loop Analysis
Not all nested loops have quadratic complexity
53
The number of iterations of the inner loop is not a function of n
for (i = 1; i <= n; i++)for (j = 1; j <= 10; j++)
System.out.println(i + j);
Loop Analysis
In this code, the inner loop is controlled by the state of the outer loop:
54
The outer loop executes n times
The inner loop executes 1 time on the first iteration of the outerloop, 2 times the second, 3 times the third, and so on
for (i = 1; i <= n; i++)for (j = 1; j <= i; j++)
System.out.println(i + j);
Loop Analysis
The time complexity of this code is
55
So the code has quadratic complexity
Remember, Big O analysis is focused on the general shape ofthe curve