Title: These notes are intended for use by students in CS0445 at the University of Pittsburgh and no one else
1(No Transcript)
2- These notes are intended for use by students in
CS0445 at the University of Pittsburgh and no one
else - These notes are provided free of charge and may
not be sold in any shape or form - Material from these notes is obtained from
various sources, including, but not limited to,
the following - Data Structures and Abstractions with Java, 2nd
and 3rd Editions by Frank Carrano - Data Structures and the Java Collections
Framework by William Collins - Classic Data Structures in Java by Timothy Budd
- Java By Dissection by Pohl and McDowell
- Java Software Solutions (various editions) by
John Lewis and William Loftus - java.sun.com and its many sub-links
3Goals of Course
- To learn, understand and be able to utilize many
of the data structures that are fundamental to
computer science - Data structures such as vectors, stacks, queues,
linked-lists and trees are used throughout
computer science - We should understand these from a user's point of
view - What are these data structures and how do I use
them in my programs?
4Goals of Course
- To understand implementation issues related to
these data structures, and to see how they can be
implemented in the Java programming language - Data structures can be implemented in various
ways, each of which has implications (ex
run-time differences, code complexity,
modifiability) - We should understand these data structures from
an implementer's point of view - How can these data structures be effectively
implemented?
5Goals of Course
- To understand and utilize programming ideas and
techniques utilized in data structure
implementation - Object-oriented programming, dynamic memory
utilization, recursion and other principles must
be understood in order to effectively implement
data structures - What tools must I know and be able to use in
order to implement data structures?
6Goals of Course
- To learn more of the Java programming language
and its features, and to become more proficient
at programming with it - Java is a very large language with extensive
capabilities - As your programming skills improve, you can
utilize more of these capabilities effectively - Since I am working with Java, how well can I
learn and use the language and its features?
7Lecture 1 Getting Started
- How and where can I use Java?
- Java is a platform-independent language, and thus
can be used on many different platforms
- In CS 0401 last term, you used Mac Minis
- Some of you may have PCs or prefer PCs in the
labs - Programs written in either place should run the
same way
Win32 PC
Java Program
Sun Workstation
8Lecture 1 Review
- Last term in CS 0401 you learned many things that
you will need to use this term - Basic Java program structure and syntax
- Java control structures and utilizing them
effectively - Loops, conditionals, etc
- Java methods and method calls
- With and without parameters
- Static methods vs instance methods
- Java variables and objects
- Instance variables vs method variables
- Objects vs references
- Dynamic nature of Java objects
9Lecture 1 Review
- Java classes
- Syntax for writing new classes
- Inheritance
- Polymorphism via method overriding and
overloading - Interfaces, how and why to use them
- Simple Java files and graphics
- Exception handling
- If you are unsure about these things, look them
over in your notes and in your CS 0401 textbook - Also read Appendices A-F in the Carrano Data
Structures text - We will briefly go over Appendices B, C and D and
review some of these concepts in the first few
lectures
10Lecture 1 Classes and Objects
- Classes are blueprints for our data
- The class structure provides a good way to
encapsulate the data and operations of a new type
together - Instance data and instance methods
- Access restrictions (i.e. data hiding through
private declarations) allow the implementation
details of the data type to be hidden from a user - public, protected and private allow various
levels of accessibility
11Lecture 1 Classes and Objects
- User of the class knows the nature of the data,
and the public methods, but NOT the
implementation details - But does not need to know them in order to use
the class - Ex BigInteger
- These are determined by the specifics of the
private data and the method implementations - We call this data abstraction
- This is related to abstract data types (ADTs),
which we will discuss shortly
12Lecture 1 Classes and Objects
- Java classes determine the structure of Java
objects - public declarations (typically methods) give the
interface and functionality of the objects - How the outside world communicates with the
objects - private declarations (typically data and some
methods) hide the implementation details from the
user - To put it another way, Java objects are instances
of Java classes
13Lecture 1 Classes and Objects
- Class declaration keywords
- public accessible outside class
- private inaccessible outside class
- protected accessible only within class and
subclasses and same package - static part of class rather than instance
shared by all instances - final constant cannot be assigned
(variables), overridden (methods) or subclassed
(classes)
14Lecture 1 References, Pointers and Memory
- Other than the primitive variables, all Java
variables are references
15Lecture 1 References, Pointers and Memory
- Be careful when comparing
- Know when you want to compare references or
contents - For reference variables, we typically need to use
a method to compare contents - ex. for strings, equals
- u.equals(s) returns true
- We can redefine equals() for our own classes as
well - Java does not allow operator overloading, so we
cannot redefine comparison operators to compare
contents must use named methods
16Lecture 2 References, Pointers and Memory
- How do references and pointers relate?
- Many programming languages (ex C, C, Pascal)
use pointer variables - Pointers are variables that store addresses of
other memory locations - Pointers allow indirect access of the data in
objects
Object A
101001
X
010010
010010
Object B
Y
101001
17Lecture 2 References, Pointers and Memory
- So the value stored in a pointer is an address
- However, if you dereference a pointer, you gain
access to the object it "points to"
X Y // Changes what X points to // X
no longer has access to // Object B
Object A
101001
X
101001
010010
Object B
Y
101001
18Lecture 2 References, Pointers and Memory
- In C, you dereference pointers using the
operator
X Y// Changes contents of object //
that X points to. The // value of X is
unchanged
Object A
101001
X
010010
010010
Object A
Y
101001
19Lecture 2 References, Pointers and Memory
- References in Java
- Behave in a way similar to pointers, but with
more restriction - Dereferencing is implicit there is no
dereference operator - Reference values (addresses) can be assigned but
they cannot be manipulated - But aliasing still occurs and you must be very
careful - Be aware of when you want a new object or a
reference to an old one
20Lecture 2 References, Pointers and Memory
- Java Memory Use
- All objects in Java are allocated dynamically
- Memory is allocated using the new operator
- Once allocated, objects exist for an indefinite
period of time - As long as there is an active reference to the
object - Objects that have no references to them are no
longer accessible in the program - Ex. Object B in slide 17
- These objects are marked for GARBAGE COLLECTION
21Lecture 2 References, Pointers and Memory
- The Java garbage collector is a process that runs
in the background during program execution - When the amount of available memory runs low, the
garbage collector reclaims objects that have been
marked for collection - A fairly sophisticated algorithm is used to
determine which objects can be garbage collected - If you take CS 1621 or CS 1622 you will likely
discuss this algorithm in more detail - If plenty of memory is available, there is a good
chance that the garbage collector will never run - See Example1.java
22Lecture 2 Building New Classes
- Java has many predefined classes
- Class library contains hundreds of classes, each
designed for a specific purpose - See API http//download.oracle.com/javase/6/docs
/api/ - However, in many situations we may need a class
that is not already defined - We will have to define it ourselves
- There are two primary techniques for doing this
- Composition (Aggregation)
- Inheritance
23Lecture 2 Composition
- With composition, we build a new class using
components (instance variables) that are from
previously defined classes - We compose the class from existent "pieces"
- "Has a" relationship between new class and old
classes - New class has no special access to its instance
variable objects - Methods in new class are often implemented by
utilizing methods from the instance variable
objects
24Lecture 2 Composition
- public class CompoClass
-
- private String name
- private Integer size
- public CompoClass(String n, int i)
-
- name new String(n)
- size new Integer(i)
-
- public setCharAt(int i, char c)
-
- StringBuilder b new StringBuilder(name)
- b.setCharAt(i, c)
- name b.toString()
-
-
- We cannot access the inner representation of the
String, and String objects are immutable, so we
must change it in the rather convoluted way shown
above
25Lecture 2 Inheritance
- With inheritance, we build a new class (subclass)
by extending a previously defined class
(superclass) - Subclass has all of the properties (data and
methods) defined in the superclass - "Is a" relationship between subclass and
superclass - Subclass is a superclass, and subclass objects
can be assigned to superclass variables - Not vice versa!
- Superclass IS NOT a subclass and superclass
objects cannot be assigned to subclass variables
26Lecture 2 Inheritance
- // Assume SubFoo is a subclass of Foo see notes
- // below and on board
- Foo f1
- SubFoo s1
- f1 new Foo() // fine
- f1 new SubFoo() // also fine however, now
we - // only have access to the public methods
and - // variables defined in class Foo()
- f1.foomethod() // fine
- f1.subfoomethod() // illegal
- ((SubFoo)f1).subfoomethod() // fine, since now
the ref. - // has been cast to the actual class
- s1 new SubFoo() // also fine now all SubFoo
- // public methods and variables are
accessible - s1.subfoomethod() fine
- s1.foomethod() // also fine
- s1 new Foo() // illegal
27Lecture 2 Polymorphism
- Allows superclass and subclass objects to be
accessed in a regular, consistent way - Array or collection of superclass references can
be used to access a mixture of superclass and
subclass objects - If a method is defined in both the superclass and
subclass (with identical signatures), the version
corresponding to each class will be used in a
call from the array - Idea is that the methods are similar in nature
but the redefinition in the subclass gears the
method more specifically to the data / properties
of the subclass
28Lecture 2 Polymorphism
- Ex. Each subclass overrides the move() method in
its own way - Animal A new Animal3
- A0 new Bird()
- A1 new Person()
- A2 new Fish()
- for (int i 0 i lt A.length i)
- Ai.move()
Animal
move()
move()
- References are all the same, but objects are not
- Method invoked is that associated with the
OBJECT, NOT with the reference
move()
29Lecture 2 Polymorphism
- Polymorphism is implemented utilizing two
important ideas - Method overriding
- A method defined in a superclass is redefined in
a subclass with an identical method signature - Since the signatures are identical, rather than
overloading the method (ad hoc polymorphism), it
is instead overriding the method - For a subclass object, the definition in the
subclass replaces the version in the superclass,
even if a superclass reference is used to access
the object - Superclass version can still be accessed via the
super reference
30Lecture 2 Polymorphism
- Dynamic (or late) binding
- The code executed for a method call is associated
with the call during run-time - The actual method executed is determined by the
type of the object, not the type of the reference - Polymorphism is very useful if we want to access
collections of mixed data types consistently - Ex A collection of different graphical figures,
each with a draw() method - Each is drawn differently, so it has a different
draw() method, but the call is consistent
31Lecture 2 Abstract Classes
- Abstract classes
- Sometimes in a class hierarchy, a class may be
defined simply to give cohesion to its subclasses - No objects of that class will ever be defined
- But instance data and methods will still be
inherited by all subclasses - This is an abstract class
- Keyword abstract used in declaration
- One or more methods declared to be abstract and
are thus not implemented - No objects may be instantiated
32Lecture 2 Abstract Classes
- Subclasses of an abstract class must implement
all abstract methods, or they too must be
declared to be abstract - Advantages
- Can still use superclass reference to access all
subclass objects in polymorphic way - However, we need to declare the methods we will
need in the superclass, even if they are abstract - No need to specifically define common data and
methods for each subclass - it is inherited - Helps to organize class hierarchy
- See API for many examples
33Lecture 3 Interfaces
- Java allows only single inheritance
- A new class can be a subclass of only one parent
(super) class - There are several reasons for this, from both the
implementation (i.e. how to do it in the compiler
and interpreter) point of view and the programmer
(i.e. how to use it effectively) point of view - However, it is sometimes useful to be able to
access an object through more than one superclass
reference
34Lecture 3 Interfaces
- Interfaces allow us to do this
- A Java interface is a named set of methods
- Think of it as an abstract class with no instance
data - Static constants are allowed
- No static methods are allowed
- Any Java class (no matter what its inheritance)
can implement an interface by implementing the
methods defined in it - A given class can implement any number of
interfaces
35Lecture 3 Interfaces
- Ex
- public interface Laughable
-
- public void laugh()
-
- public interface Booable
-
- public void boo()
-
- Any Java class can implement Laughable by
implementing the method laugh() - Any Java class can implement Booable by
implementing the method boo()
36Lecture 3 Interfaces
- Ex
- public class Comedian implements Laughable,
Booable -
- // various methods here (constructor, etc.)
- public void laugh()
-
- System.out.println(Ha ha ha)
-
- public void boo()
-
- System.out.println(You stink!)
-
-
37Lecture 3 Interfaces
- Recall our previous discussion of polymorphism
- This behavior also applies to interfaces the
interface acts as a superclass and the
implementing classes implement the actual methods
however they want - An interface variable can be used to reference
any object that implements that interface - However, only the interface methods are
accessible through the interface reference - Ex
- Laughable funny new Laughable3
- funny0 new Comedian()
- funny1 new SitCom() // implements Laughable
- funny2 new Clown() // implements Laughable
- for (int i 0 i lt funny.length i)
- funnyi.laugh()
- See ex16.java, Laughable.java and Booable.java
from CS 0401 Handouts
38Lecture 3 Generic Operations
- Lets look at a simple example that should
already be familiar to you Sorting - In CS 401 you should have discussed selection
sort - Simple algorithm
- Find smallest, swap into location 0
- Find next smallest, swap into location 1, etc.
- What if we want to sort different types (ints,
doubles, Strings, or any Java type)? - We need to write a different method for each
one!!! - The argument array must match the parameter array
- Or do we??
- Can we write a single method that can sort
anything? - Use an interface! Discuss
39Lecture 3 Generic Operations
- Consider the (old) Comparable interface
- It contains one method
- int compareTo(Object r)
- Returns a negative number if the current object
is less than r, 0 if the current object equals r
and a positive number if the current object is
greater than r - Look at Comparable in the API
- Consider what we need to know to sort data
- is Ai less than, equal to or greater than Aj
- Thus, we can sort Comparable data without knowing
anything else about it - Awesome!
- Polymorphism allows this to work
40Lecture 3 Generic Operations
- Think of the objects we want to sort as black
boxes - We know we can compare them because they
implement Comparable - We dont know (or need to know) anything else
about them even though they may have many other
methods / instance variables - Show on board
- Thus, a single sort method will work for an array
of any Comparable class - Did I mention that this was awesome!?
41Lecture 3 "Generic" Operations
- Note In JDK 1.5 Java improved its generic
abilities by introducing parameterized types,
interfaces and methods - We will discuss these in more detail at different
points throughout the term - Right now, let's just look at the Comparable
interface - Old Version
- public interface Comparable
- public int compareTo(Object rhs)
- New Version
- public interface ComparableltTgt
- public int compareTo(T rhs)
42Lecture 3 "Generic" Operations
- Both versions allow arbitrary objects to be
compared - The difference is that in the parameterized
version, the types of the objects can be
established and checked at compile-time - With the original version, this could not be done
until run-time - To see this consider the parameter to the
compareTo() method - In the orginal version it is Object
- In the parameterized version it is T (i.e.
whichever type is passed into the parameter)
43Lecture 3 "Generic" Operations
- Now, for 2 objects, C1 and C2, consider the call
- C1.compareTo(C2)
- In the orginal version, the compiler could not do
any type checking, since C2 can be any Object - So if C2's object was incompatible with C1's
object (i.e. apples and oranges) this problem
would not be known until program execution - In the new version, the compiler can check the
type of C2 and make sure it matches with the type
set for T in the definition of compareTo - If the types are incompatible, the compiler will
give an error
44Lecture 3 "Generic" Operations
- Why do we care?
- Compilation errors are typically much easier to
resolve than run-time errors - We'd like to "push" as much of the error-checking
as possible to compile-time, while preserving the
flexibility of the language - Parameterized types allow this to be done
- Let's put all of this together in another handout
- See Example2.java, People.java, Worker.java,
Student.java, SortArray.java
45Lecture 3 More on Java Generics
- Java allows for generic interfaces, classes and
methods - We saw interface example ComparableltTgt
- Let's look at a simple class example and a simple
method example - We will revisit this topic again probably more
than once - Let's try to (very simply) mimic the
functionality of a Java array - We want to be a create an object with an
arbitrary number of locations - However, once created, the size is fixed
46Lecture 3 More on Java Generics
- We want the underlying type to be any Java type
- However, it should be homogeneous cannot mix
types (except if type is a superclass) - We want to be able to assign a value to a
location - We want to be able to retrieve a value from a
location - We want to be able to tell the size of the array
- Let's see how to do this with Java Generics
- See MyArray.java and Example3.java
- Note that MyArray is not really a useful type
it is just meant to demonstrate parameterized
Java types
47Lecture 4 Abstract Data Types
- Abstract Data Types (ADTs)
- We are familiar with data types in Java
- For example some primitive data types int,
float, double, boolean, or reference types such
as String - We can think of these as a combination (or
encapsulation) of two things - The data itself and its representation in memory
- For classes these are the instance variables
- The operations by which the data can be
manipulated - For classes these are the methods
48Lecture 4 Abstract Data Types
- For example, the int type in Java
- We can think of it simply as whole numbers,
represented in some way in the computer, but this
would be incomplete - What makes integers useful is the operations that
we can do on them, for example , -, , /, and
others - It is understanding the nature of the data
together with the operations that can be done on
it that make ints useful to us - We also discussed BigInteger previously
49Lecture 4 Abstract Data Types
- So where does the abstract part come in?
- Note that in order to use ints in our programs,
we ONLY need to know what they are and what their
operations are - We do NOT need to know their implementation
details - Does it matter to me how the int or BigInteger is
represented in memory? - Does it matter how the actual division operation
is done on the computer? - For the purposes of using integers effectively in
most situationsNO!
50Lecture 4 Abstract Data Types
- More generally speaking, an ADT is a data type
(data operations) whose functionality is
separated from its implementation - The same functionality can result from different
implementations - Users of the ADT need only to know the
functionality - Naturally, however, to actually be used, ADTs
must be implemented by someone at some point - Implementer must be concerned with the
implementation details - In this course you will look at ADTs both from
the user's and implementer's point of view
51Lecture 4 ADTs vs. Classes
- The previous slides should be familiar to you
- We have already discussed the idea of data
abstraction from classes - ADTs are language-independent representations of
data types - Can be used to specify a new data type that can
then be implemented in various ways using
different programming languages - Classes are language-specific structures that
allow implementation of ADTs - Only exist in object-oriented or object-based
languages
52Lecture 4 ADTs vs. Classes
- A given ADT can be implemented in different ways
using different classes - We will see some of these soon
- Ex Stack, Queue, SortedList can be implemented
in different ways - A given class can in fact be used to represent
more than one ADT - The Java class ArrayList can be used to represent
a Stack, Queue, Deque and other ADTs
53Lecture 4 Interfaces as ADTs
- Consider again interfaces
- Specify a set of methods, or, more generally a
set of behaviors or abilities - Do not specify how those methods are actually
implemented - Do not even specify the data upon which the
methods depend - These fit reasonably well with ADTs
- ADTs DO specify the data, but we can infer much
about the data based on the methods
54Lecture 4 Interfaces as ADTs
- The text will typically use interfaces as ADTs
and classes as ADT implementations - Using the interface we will have to rely on
descriptions for the data rather than actual data - The data itself is left unspecified and will be
detailed in the class(es) that implement the
interfaces - This is ok since the data is typically specific
to an implementation anyway - Ex ADT Stack
- Push an object onto the top of the Stack
- Pop an object off the top of the Stack
- At this (ADT) level we don't care how the data is
actually represented, as long as the methods work
as specified
55Lecture 4 ADTs for Collections of Data
- Many ADTs (especially in this course) are used to
represent collections of data - Multiple objects organized and accessed in a
particular way - The organization and access is specified by the
ADT - Done through interfaces in Java
- The specific implementation of the data and
operations can be done in various ways - Done through classes in Java
- We will examine many of these this term!
56Lecture 4 ADT Bag
- Consider our first detailed ADT the Bag
- Think of a real bag in which we can place things
- No rule about how many items to put in
- No rule about the order of the items
- No rule about duplicate items
- No rule about what type of items to put in
- However, we will make it homogeneous by requiring
the items to be the same class or subclass of a
specific Java type - Lets look at the interface
- See BagInterface.java
57Lecture 4 ADT Bag
- Note what is NOT in the interface
- Any specification of the data for the collection
- We will leave this to the implementation
- The interface specifies the behaviors only
- However, the implementation is at least partially
implied - Must be some type of collection
- Any implementation of the methods
- Note that other things are not explicitly in the
interface but maybe should be - Ex What the method should do
- Ex How special cases should be handled
- We typically have to handle these via comments
58Lecture 4 ADT Bag
- Ex public boolean add(T newEntry)
- We want to consider specifications from two
points of view - What is the purpose / effect of the operation in
the normal case? - What unusual / erroneous situations can occur and
how do we handle them? - The first point can be handled via preconditions
and postconditions - Preconditions indicate what is assumed to be the
state of the ADT prior to the method's execution - Postconditions indicate what is the state of the
ADT aftter the method's execution - From the two we can infer the method's effect
59Lecture 4 ADT Bag
- Ex for add(newEntry) we might have
- Precondition
- Bag is in a valid state containing N items
- Postconditions
- Bag is in a valid state containing N1 items
- newEntry is now contained in the Bag
- This is somewhat mathematical, so many ADTs also
have operation descriptions explaining the
operation in plainer terms - More complex operations may also have more
complex conditions - However, pre and postconditions can be very
important for verifying correctness of methods
60Lecture 4 ADT Bag
- The second point is often trickier to handle
- Sometimes the unusual / erroneous circumstances
are not obvious - Often they can be handled in more than one way
- Ex for add(newEntry) we might have
- Bag is not valid to begin with due to previous
error - newEntry is not a valid object
- Assuming we detect the problem, we could handle
it by - Doing a "no op"
- Returning a false boolean value
- Throwing an exception
- We need to make these clear to the user of the
ADT so he/she knows what to expect
61Lecture 4 Using a Bag
- A Bag is a simple ADT, but it can still be useful
- See examples in text
- Here is another simple one
- Generate some random integers and count how many
of each number were generated - There are many ways to do this, but one is with a
bag - See Example4.java
- Q Is this the most efficient way of doing this?
- A Hard to tell unless we can see how the Bag is
implemented - Lets do that next!
62Lecture 5 Implementing a Bag
- Ok, now we need to look at a Bag from the
implementer's point of view - How to represent the data?
- Must somehow represent a collection of items
(Objects) - How to implement the operations?
- Clearly, the implementation of the operations
will be closely related to the representation of
the data - Minimally the data representation will "suggest"
ways of implementing the operations
63Lecture 5 Array Implementation of a Bag
- Let's first consider using an array
- Makes sense since it can store multiple values
and allow them to be manipulated in various ways - private Object bag // old way
- private T bag // current way
- Ok, but is just an array enough?
- We know the size of an array object, once created
is fixed - We also know that our Bag must be able to change
in size (with adds and removes)
64Lecture 5 Array Implementation of a Bag
- Thus we need to create our array, then keep track
of how many locations are used with some other
variable - private int numberOfEntries
- But how big to make the array?
- What if we run out of room?
- Note that the above questions are (mostly)
irrelevant to the client, but are quite important
to the implementer - Two approaches to take
- Use a fixed size and when it fills it fills
- Dynamically resize when necessary (transparently)
65Lecture 5 Fixed Size Array
- Fixed Size Array
- Idea
- Initialize array in the constructor
- Size is passed in as a parameter
- Once created, the size is constant as long as the
list is being used - Once array fills, any "add" operations will fail
until space is freed (through "remove" or
"clear") - Advantage?
- Easier for programmer to implement
66Lecture 5 Fixed Size Array
- Disadvantages
- ADT user (programmer) may greatly over-allocate
the array, wasting space - Overcompensates to not run out of room
- Program user (non-programmer) may run out of room
at run-time - If programmer does not do above
- Neither of these is desirable
- However, let's briefly look at this
implementation anyway - Much of it will be the same for the dynamic
structure - Only differences are when array fills
67Lecture 5 Fixed Size Array
- Let's start with the simple method we have been
discussing - public boolean add (T newEntry)
-
- // what do we need to do in the normal case?
- // what do we do in the abnormal case?
-
- Recall our data
- private T bag
- private int numberOfEntries
- Let's figure this out
- See board
68Lecture 5 Fixed Size Array
- Lets look at code from text
- public boolean add(T newEntry)
-
- boolean result true
- if (isFull())
-
- result false
-
- else
- // assertion result is true here
- bagnumberOfEntries newEntry
- numberOfEntries
- // end if
- return result
- // end add
69Lecture 5 Fixed Size Array
- How about a bit more complicated operation?
- public boolean remove(T anEntry)
-
- What do we need to do here?
- Think of the normal case
- Must first find the item
- Then must remove it
- How?
- Think of unusual or special cases
- Lets work up some code / pseudocode on the board
70Lecture 5 Fixed Size Array
- Consider the authors code
- /
- Removes one occurrence of a given entry from this
bag. - _at_param anEntry the entry to be removed
- _at_return true if the removal was successful, or
false - otherwise
- /
- public boolean remove(T anEntry)
-
- int index getIndexOf(anEntry)
- T result removeEntry(index)
- return anEntry.equals(result)
- // end remove
71Lecture 5 Fixed Size Array
- private int getIndexOf(T anEntry)
-
- int where -1
- boolean found false
- for (int index 0
- !found (index lt numberOfEntries) index)
-
- if (anEntry.equals(bagindex))
-
- found true
- where index
- // end if
- // end for
-
- return where
- // end getIndexOf
72Lecture 5 Fixed Size Array
- private T removeEntry(int givenIndex)
-
- T result null
-
- if (!isEmpty() (givenIndex gt 0))
-
- result baggivenIndex // entry to
remove - numberOfEntries--
- baggivenIndex bagnumberOfEntries
- // replace entry to remove with last entry
- bagnumberOfEntries null
- // remove reference to last entry
- // end if
- return result
- // end removeEntry
73Lecture 5 Fixed Size Array
- Approach to implementing the other methods should
be the same - What is the method supposed to do?
- What can go wrong and what do we do about it?
- Does our code do what we want it to do?
- See text for discussion of more operations
- See ArrayBag.java for entire implementation
- Note Due to publisher restrictions, I am putting
the authors implementations in a directory that
is not accessible outside of Pitts domain - If you want to access these you must do so from a
Pitt IP address
74Lecture 5 Dynamic Size Array
- Dynamic Size Array
- Idea
- Array is created of some initial size
- Constructor can allow programmer to pass the size
in, or we can choose some default initial size - If this array becomes filled, we must
- Create a new, bigger array
- Copy the data from the old array into the new one
- Assign the new array as our working array
- Some questions
- How big to make the new array?
- How do we copy?
- What happens to the old array?
75Lecture 5 Dynamic Size Array
- How big to make the new array?
- Clearly it must be bigger than the old array, but
how much bigger? - What must we consider when deciding the size?
- If we make the new array too small, we will have
to resize often, causing a lot of overhead - If we make the new array too large, we will be
wasting a lot of memory
- Let's make the new array 2X the size of the old
one - This way we have a lot of new space but are not
using outrageously more than we had before - We will see more specifically why this was chosen
later
76Lecture 5 Dynamic Size Array
- How do we copy?
- This is pretty easy just start at the beginning
of the old array and copy index by index into the
new array - Note that we are copying references, so the
objects in the new array are the same objects
that were in the old array - What happens to the old array?
- It is garbage collected
- Let's try this on the board, then look at code
- See ResizableArrayBag.java and Example5.java
- Note how it is largely the same as ArrayBag.java
77Lecture 5 Dynamic Size Array
- Let's look in particular at the resizing process
- Resizing is initiated when an add is performed on
a list with a full array - Only difference from ArrayBag is ensureCapacity()
- The resizing process is transparent to the user
of the ResizableArrayBag class - For this operation, add() always succeeds
public boolean add(T newEntry) ensureCapacity()
// add new entry after last current
entry bagnumberOfEntries newEntry numberOfE
ntries return true // end add
78Lecture 5 Dynamic Size Array
- So what does ensureCapacity() do?
- Private method to do what we described
- See Arrays.copyOf() API
- Note that instance variable numberOfEntries is
not changed - Why?
private void ensureCapacity() if
(numberOfEntries bag.length) bag
Arrays.copyOf(bag, 2 bag.length) // end
ensureCapacity
79Lecture 5 Contiguous Memory Data Structures
- Both Bag implementations so far use contiguous
memory - Locations are located next to each other in
memory - Given the address of the first location, we can
find all of the others based on an offset from
the first - Benefits of contiguous memory
- We have direct access to individual items
- Access of item Ai can be done in a single
operation
0 1 i i1
80Lecture 5 Contiguous Memory
- Direct access allows us to use efficient
algorithms such as Binary Search to find an item - Arrays and array-based DS are also fairly simple
and easy to use - Drawbacks of contiguous memory
- Allocation of the memory must be done at once, in
a large block as we just discussed - If we allocate too much memory we are being
wasteful - If we do not allocate enough, we will run out
- We have seen how our Bag can resize
transparently, but recall that this requires
allocating new memory and copying into it, which
takes time to do
81Lecture 5 Contiguous Memory
- Inserting or deleting data "at the middle" of an
array may require shifting of the other elements - Also requires some time to do
- We did not need to do this with our Bag, but
other data structures (ex Lists) may require
this - We will discuss the details of "how much" time is
required later - This deals with algorithm analysis
82Lecture 6 Linked Data Structures
- Let's concentrate on the drawbacks of contiguous
memory - Is there an alternative way of storing a
collection of data that avoids these problems? - What if we can allocate our memory in small,
separate pieces, one for each item in the
collection - Now we allocate exactly as many pieces as we need
- Now we do not have to shift items, since all of
the items are separate anyway - Draw on board
83Lecture 6 Linked Data Structures
- But how do we keep track of all of the pieces?
- We let the pieces keep track of each other!
- Let each piece have 2 parts to it
- One part for the data it is storing
- One part to store the location of the next piece
- This is the idea behind a linked-list
firstNode
data
data
data
data
84Lecture 6 Linked Data Structures
- Idea of Linked List
- If we know where the beginning of the list is
- And each link knows where the next one is
- Then we can access all of the items in the list
- Our problems with contiguous memory now go away
- Allocation can be done one link at a time, for as
many links as we need - New links can be "linked up" anywhere in the
list, without shifting needed - Demonstrate on board
85Lecture 6 Linked Lists
- How can we implement linked lists?
- The key is how each link is implemented
- As we said, two parts are needed, one for data
and one to store the location of the next link - We can do this with a self-referential data type
- class Node
-
- private T data
- private Node next
-
- A NODE is a common name for a link in a
linked-list - Note why it is called "self-referential"
86Lecture 6 Singly Linked Lists
- Linked-List Implementation Variations
- Singly Linked List
- The simple linked-list we just discussed is a
singly-linked list - Links go in one direction only
- We can easily traverse the list from the front to
the rear - We CANNOT go backwards through the list at all
- This list is simple and (relatively) easy to
implement, but has the limitations of any "one
way street" - This implementation is developed in Chapter 3
firstNode
87Lecture 6 Singly Linked Lists
- There are other variations of linked lists
- Doubly linked list
- Circular linked list
- We will discuss these shortly
- For now we will keep things very simple
88Lecture 6 Linked Bag Implementation
- Let's look at this implementation a bit
- public class LinkedBagltTgt implements
BagInterfaceltTgt -
- private Node firstNode
- private int numberOfEntries
-
- private class Node
-
- private T data
- private Node next
- private Node(T dataPortion)
- this(dataPortion, null)
-
- private Node(T dataPortion, Node nextNode)
- data dataPortion next nextNode
- // class Node
-
- // class LinkedBag
89Lecture 6 Node As an Inner Class
- Why is it done this way?
- Since Node is declared within LinkedBag, methods
in LinkedBag can access private declarations
within Node - This is a way to get "around" the protection of
the private data - LinkedBag will be needing to access data and next
of its Nodes in many of its methods - We could write accessors and mutators within Node
to allow this access - However, it is simpler for the programmer if we
can access data and next directly - They are still private and cannot be accessed
outside of LinkedBag - On the downside, with this implementation, we
cannot use Node outside of the LinkedBag class
90Lecture 6 Linked Bag Implementation
- Now let's see how we would implement some of our
BagInterface methods - public boolean add (T newEntry)
-
- Node newNode new Node(newEntry) // create
Node - newNode.next firstNode // link it to prev.
front - firstNode newNode // set front to new Node
- numberofEntries // increment entries
- return true
- // method add
- Compare to add() in the array implementation
- What is different?
- Is this a problem?
91Lecture 6 Linked Bag Implementation
- Trace on board
- Try a few adds in example
- Note insertion is at the front of the bag
- New node is created and newEntry is put in it
- New node becomes new front of list, push old
front back - Are there any special cases
- Ex What if the bag is empty?
- firstNode will be null