Title: CSC 262
1CSC 262
- Computer Programming II
- Data Structures, Abstract Data Types,
Object-Oriented Programming - We expand on the topics of CSC 260 and focus on
- building data structures
- encapsulating data structures and the code that
manipulates them - further explore object-oriented programming
- introduce a variety of types (collections,
ordered lists, queues, stacks) - explore computational complexity
- introduce recursion
- explore searching and sorting algorithms
- review exception handling, I/O with files,
interfaces
2Chapter 1 Software Development
- Phases of the software development lifecycle
- Specification of the task
- Design of the solution
- Implementation of the solution (coding)
- Analysis of the solution
- Testing and debugging
- Maintaining and evolution of the system
- Obsolescence
- We will combine 4 and 5, add Documentation to
6, and remove 7! - Before we examine the software lifecycle in
detail, lets look over some definitions
3Definitions
- Object-oriented programming (OOP)
- taking ADTs further by including such abilities
as inheritance, message passing and polymorphism - Code Reuse
- a feature of OOP supported by inheritance the
ability to reuse a previously written class
through inheritance - Procedural Abstraction
- an older form of abstraction, using methods
(procedures) to perform specific tasks. This is
a way to implement information hiding
- Data Structures
- collection of data in some organization
- Encapsulation
- collecting data structures and the operations
that manipulate them into one structural entity
(one definition or package or file) - Information Hiding
- ensuring that outside users of a data structure
cannot directly manipulate the data structure,
but instead, force the outsider users to
manipulate the data structures through the
encapsulated operations - Abstract Data Type (ADT)
- a data structure which provides both
encapsulation and information hiding
4Problem Specification
- The first stage in the software development
lifecycle is to clearly specify the problem - Specification includes
- Understanding the problem
- Coming up with a platform for the solution (what
language, what machine type, what is the input,
what should the output look like?) - The specification should be provided in a formal
way to be referenced by others involved in the
problem solving efforts - We will not only create specifications for the
problem in general, but for each class and each
method - The book uses this approach to aid development of
example code get used to it!
5Example Specification
- Example a method to convert from Celsius to
Fahrenheit - Public static double celsiusToFahrenheit(double
C) - Convert a temperature from Celsius degrees to
Fahrenheit degrees - Parameters
- c a temperature in degrees Celsius
- Precondition
- c - 273.16
- Returns
- The temperature c converted to Fahrenheit degrees
- Throws List
- IllegalArgumentException indicates that c is
less than the smallest Celsius temperature
(-273.16)
- A method specification will consist of
- a short introduction (including the complete
header of the method), - a description of the parameters,
- preconditions,
- description of what is to be returned (the
methods postcondition), - and throws lists (what exceptions, if they
arise, should be thrown)
6Providing Specifications
- It is important that a programmer provide the
specifications for how a method is intended to be
used - This information can help another programmer use
the method correctly - Place the preconditions and postcondition(s) in
comments prior to the method itself - In Java, this information can be viewed in a
.class file even though you cant see the code
itself
// Precondition x 0. // Postcondition
The square root of x has // been written to
the standard output. public void writeSqrt(
double x)
// Precondition letter is an uppercase or //
lowercase letter (in the range 'A' ... 'Z, 'a'
... 'z') // Postcondition The value returned
by the // method is true if letter is a
vowel // otherwise the value returned by the
method is // false. public boolean isVowel(
char letter )
7Design
- Perhaps the most critical phase of the software
cycle is the design - Here, we figure out how to solve the problem by
creating the design of the program - The design is created using decomposition
- This indicates what components are needed in the
design what methods, and how they will relate
to each other - We sometimes create a top-down design to
illustrate this decomposition - Next, we specify the sequence of operations using
an algorithm, written in pseudocode - Thus, we create a design in at least two levels
of specificity, if not more - Older designs used flowcharts to indicate control
flow, pseudocode is adequate for this
8Example Decomposition
- Problem create a conversion chart between
Celsius and Fahrenheit for temperatures between 0
and 100 C (by units of 10) - Design
- Display the labels at the top of the chart
- Repeat for each line in the chart
- Set celsius equal to the next Celsius temperature
- Compute fahrenheit given celsius
- Print celsius rounded to nearest hundredth
- Print the letter C
- Print some blank spaces
- Print fahrenheit rounded to the nearest hundredth
- Print the letter F
- Return the cursor
- Print lines to indicate the bottom of the table
- - indicates that these instructions can be done
using separate methods to promote procedural
abstraction
9Implementation
- Given a good design, creating the program is
easy! - The decomposition illustrates the following
- Control structures
- a loop, what kind?
- Since we know the starting and ending points, a
for loop - Variables
- celsius
- fahrenheit
- a loop variable
- we can use constants or literals for 0 and 100
- Methods
- rounding off a value to the nearest hundredth
- converting Celsius to Fahrenheit
10Exception Handling
- The decomposition did not tell us what exceptions
to handle - We need to think about this when specifying a
method - Exceptions situations that arise that might be
of interest or might cause a run-time error - Exception Handlers code that will handle an
exception when it arises - Java offers many built-in exceptions and
exception handlers that we can use, or we can
build our own
11Three ways to handle Exceptions
- Add throws exceptiontype to the method header
- If that type of exception arises, the method will
execute throw exceptiontype which is handled by
that class exception handler - Example add throws IOException to the method if
it is suspected that the method may contain an IO
exception note that this requires importing the
IOException class - Use if statements to explicitly look for an
exception and if found, throw the exception - Example
- if (c n (Argument c is too small)
- Place the code that might raise the exception in
a try-catch block - try // code goes here
- catch (exceptiontype e) // code goes here
- You can have as many catch blocks as you want,
one for each type of exception that might be
caught
12How and When to Throw Exceptions
- When
- if there is a situation where your program may
cause a run-time error, use an exception handler - How
- Using throws Exception will cause the program to
terminate, not necessarily a good move - You can explicitly look for an exception and if
found, throw it - this will also cause the program to terminate,
but the message you include may provide you a
clue in debugging the program - try catch block is useful if you do not want
the program to terminate
// Precondition x 0. // Postcondition
Square root of x has been written to standard
output public void writeSqrt( double x) if
(x
(Negative x)
13Computational Complexity
- There are numerous ways to solve a problem
- What makes one way better than another?
- Simplicity
- Accuracy
- Correctness
- User-friendliness
- Computational Complexity
- Computational Complexity is a mathematical way to
determine how efficient your code is - Book refers to this as run-time analysis
- Count the number of instructions executed for
your algorithm when executed on input of size n - We can compare algorithms to determine which has
the best computational complexity - It turns out that the complexity of an algorithm
has more of an impact on a computers performance
than the speed of the processor
14Example Stairs Counting
- You and a friend are at the top of the Eiffel
Tower - Your friend asks how many steps are there?
- 3 approaches
- Walk down and keep a tally for each step, write
a mark on a sheet of paper, then return to the
top - Have your friend keep tally, each time you get to
a new step, put your hat there, run back up and
tell your friend to write another mark, then go
back to the step with your hat and repeat until
you have reached the bottom, then return to the
top - Ask someone else!
15Complexities of the 3 Approaches
- The Eiffel Tower has 2689 steps
- First approach walk down 1 step, write a check
mark, walk down second step, write a checkmark,
etc until you reach the bottom, then return - 2689 steps, so 2689 2 operations going down
plus 2689 steps returning, or 2689 3 8067
operations - Second approach walk down one step, return to
the top to tell your friend to make a mark,
repeat for step 2 (2 down, 2 back, mark) and for
step 3, etc until you reach the bottom - Takes 2 (1 2 3 2689) 2689 total
operations - Note that 1 2 3 n n (n 1) / 2, for
n 2689, this is 3,616,705 - The second approach then takes 3,616,705 2
2689 7,236,099 operations! - Third approach ask someone then pass on the
answer, 2 operations (1 input and 1 output)
16Big-O Notation
- This defines the computational complexity of some
code given input of size n - If the number of operations is bounded by f(n)c,
where f is a function and c is some constant,
then we say that the complexity of the code is
O(f(n)) - We boil down Big-O notation to one of
- O(1) constant time
- O(log n) logarimthic time
- O(n) linear time
- O(n log n)
- O(n2) quadratic time
- O(nx) some other polynomial time
- O(2n) exponential time
17Eiffel Tower Solution Complexities
- Solution 1 took 3 2689 operations
- This is 3 n or c n, so this becomes O(n)
- Solution 2 took 2 (1 2 3 2689) 2689
2 (n (n 1) / 2) 2689 2 n2 / 2
n / 2 n - This has the form c1 n2 c2 n n
- We round this off to c1 n2 which is O(n2)
- Solution 3 took 2 steps (1 input, 1 output)
- Notice that no matter how many steps there were,
we have a constant number of operations, 2, so
this is O(1) - If the Eiffel Tower had 1,000,000 steps instead
of 2689, solutions 1 and 2 will have a different
number of operations but solution 3 will stay
take 2 operations
18Comparison of Complexities
19Best/Average/Worst Case
- Notice in our Eiffel Tower example
- the three complexities were based on the size of
n, but no other factors - Some algorithms are not only dependent on the
size of the input, but what the input is - Consider searching for an item in a list where
the item is the first item, how long does it
take? - What if you are looking for an item and it is the
last item? - Problems that are input-dependent may have
different complexities depending on the input
- These describe best versus worst-case situations
- Best case the complexity of the algorithm when
the input is in such a form that it provides the
for the least number of operations necessary - Worst case the complexity of the algorithm when
input is in a form that requires the most number
of operations necessary - Average case the complexity required to solve
the average problem (or on average, what is the
complexity?)
20Example Sequential Search
- Here is a simple loop to find the location of a
particular item in an array - while(target!ai) i
- Assume the array stores n items
- Best case complexity O(1) find it in the
first location - Worst case complexity O(n) find it in the
last location (or it is not found at all) - Average case complexity on average, we will
find the item in location (n/2) giving a
complexity of O(n/2) which is O(n c) or O(n) - We can also compute this by finding the number of
operations needed to find every element, and
dividing the result by n - What is the complexity of searching using a
for-loop? - for(i0i
21Example Selection Sort
- for(j0j
-
- smallest aj
- location j
- for(kjk
-
- if (ak
-
- smallest ak
- location k
-
- temp aj
- aj alocation
- alocation temp
-
-
- Two for-loops
- Outer loop iterates from 0 to n-2
- Inner loop iterates from j to n-1
- the first time it iterates n-1 times
- the second time it iterates n-2 times
- the third time it iterates n-3 times
- the last time it iterates once
- The number of operations is then
- (n-1) (n-2) (n-3) 1
- this is equal to n (n-1) / 2
- Therefore, Selection Sort has complexity of O(n2)
so it has the same best, worst and average case
complexity
22Example Insertion Sort
- We have a for-loop and a nested while loop
- How many times will the for-loop iterate? n-1
- How many times will the inner while loop iterate
each time through? - could be 0, could be j, so somewhere between 0
and j - The number of operations range between
- n-1 1 to n-1 j
- where j goes from 1 to n-1
- Best case O(n)
- Worst case O(n2)
- Average case O(n2)
- for(j1 j
-
- current aj
- position j
- while(position 0
- aposition-1 current)
-
- aposition aposition-1
- position--
-
- aposition current
-
23Testing and Debugging
- The last phase of the software lifecycle that we
will consider in this course - How do you determine if your program is working
correctly? - Test it out on a variety of data
- Know the correct output when you test your
program! - What data?
- Try boundary values
- Try values outside of legal ranges to see if your
exceptions are handled properly - The book contains some tips on debugging, see
pages 30-31