Title: CS2
1CS2
- Module 24
- Category CS Concepts
- Topic Linked Lists
- Objectives
- Linked Lists
- Programming Tips
2CS 2
- Introduction to
- Object Oriented Programming
- Module 24
- CS Concepts
- Linked Lists
3Evolving Data Structures Linked Lists
4!
Imagine you just broke up with your girlfriend...
Here, certain gender assumptions are made. Bear
with us.
5Linked Lists Review
Its time to clean off your desk. Time to
replace your photographs
She was no good for you anyway.
6So, you put the old photograph in a box (just in
case she calls).
... next to the boxes holding pictures of the
other celebrities you once dated.
7And then it hits you
cs2 can help organize the wreckage that is your
social life.
8How So?
Instead of using boxes, it might be better to use
a linked list structure.
Mistakes I Have Made
9How So?
Instead of using boxes, it might be better to use
a linked list structure.
Mistakes I Have Made
10How So?
Instead of using boxes, it might be better to use
a linked list structure.
Mistakes I Have Made
11How So?
Instead of using boxes, it might be better to use
a linked list structure.
Mistakes I Have Made
12How So?
Instead of using boxes, it might be better to use
a linked list structure.
Mistakes I Have Made
13How So?
Instead of using boxes, it might be better to use
a linked list structure.
Mistakes I Have Made
14Immediately you start coding
15public class Picture private String
strName private Picture next public
Picture (String strNome) setName(strName) setN
ext(null) public void setNext(Picture
next) this.next next public
Picture getNext() return next
public String getName() return strName
public void setName(String strName) this.strNa
me strName // Picture
Looks good. Are we done coding this class?
No. Wheres the debug main?
You might think DEBUG MAIN? Who needs a debug
main?
You do!
16OK, OK
public static void main(String arguments)
Picture pTest new Picture ("Britany
Spears") String strTemp pTest.getName() Syst
em.out.println ("I was dumped by " strTemp)
// main
Alright, so you decide to code a test main for
this dinky little class. What a bother.
17Eh? What Happened?
When you test the class, you find, to your
complete surprise, that theres a bug.
18public class Picture private String
strName private Picture next public
Picture (String strNome) setName(strName) setN
ext(null) public void setNext(Picture
next) this.next next public
Picture getNext() return next
public String getName() return strName
public void setName(String strName) this.strNa
me strName // Picture
But my code compiled. You explain to your TA.
Mere compilation is insignificant compared to
the power of debugging.
19Prepare the Autograder to fire on the debug main
20public class Picture private String
strName private Picture next public
Picture (String strNome) setName(strName) setN
ext(null) public void setNext(Picture
next) this.next next public
Picture getNext() return next
public String getName() return strName
public void setName(String strName) this.strNa
me strName public static void
main(String args) Picture pTest new
Picture ("Britany Spears") String strTemp
pTest.getName() System.out.println ("I was
dumped by " strTemp) // main // Picture
Wheres the bug?
Good. So a few of you alert folks spotted
it. Now. How long would it take you to find
this bug if you had 12 classes and 2,500 lines of
code to sort through?
at 3 a.m...?
21You protest But I tried to just code the
classes--
22What Else is Missing?
Lesson learned ALWAYS use a debug main. But
what else have we forgotten?
public String toString() public boolean
equals(Object o)
23 public String toString() return "Picture
of " getName() public boolean
equals (Object oTemp) boolean answer
false if (oTemp instanceof Picture)
Picture pic (Picture) oTemp if
(pic.getName().equals(getName())) answer
true return answer
public static void main(String args) Picture
pTest new Picture ("Britany Spears") String
strTemp pTest.getName() System.out.println
("I was dumped by " strTemp) Picture pSecond
new Picture ("Britany Spears") System.out.prin
tln ("Picture 1 " pTest) System.out.println
("Picture 2 " pSecond) System.out.println
("Equals? " pTest.equals(pSecond)) Integer
iTemp new Integer (42) System.out.println
("Is Britany equal to an Integer? "
pTest.equals(iTemp))
After fixing our bug, we continue
New methods? TEST THEM
24Invest 5 minutes doing trivial tests as you make
the class. . . . . . or spend hours searching
through reams of code later.
25Are we done with this class?
NO. Our debug main tests all the methods, but
does not test all the conditions. We failed to
compare two different Picture objects.
26Doh!
So, we add more to our main, so that each
expected condition for each method gets tested
27 public boolean equals (Object oTemp) boolean
answer false if (oTemp instanceof Picture)
Picture pic (Picture) oTemp if
(pic.getName().equals(getName())) answer
true return answer public
static void main(String args) Picture pTest
new Picture ("Britany Spears") System.out.prin
tln ("I was dumped by " pTest.getName()) Pict
ure pSecond new Picture ("Britany
Spears") System.out.println ("Picture 1 "
pTest) System.out.println ("Picture 2 "
pSecond) System.out.println ("Equals? "
pTest.equals(pSecond)) Integer iTemp new
Integer (42) System.out.println ("Is Britany
equal to an Integer? "
pTest.equals(iTemp)) Picture pThird new
Picture ("Chewbacca") System.out.println ("Is
Britany equal to Chewbacca? "
pThird.equals(pTest))
Why did our equals() method fail? Trace the code
28Were Not Kidding
Your debug main MUST a) Test all the methods
in the class, no matter how trivial, b) Test
all the conditions that the methods are expected
to handle, no matter how trivial.
29((W(h)e)re)?
Where Were We?
- So weve just finished creating a class to
represent our old photographs. - It differs from a mere record class from cs1, in
that weve also included modifiers for each
instance variable. That is, the class also has
methods that provides access to the variables,
and lets us change things.
- We have fields for data
- A String reference
- A next Picture reference
- We have accessors/modifiers (aka getters
setters) - We override the inherited Object methods
- toString() - which otherwise prints memory
address related info - equals() - which otherwise uses
- We wrote a debug main, to avoid trouble.
30public class PictureCollection private
Picture head
We start with a PictureCollection class. We need
an instance variable to act as the head node.
We make it private because (a) this concerns
our personal picture collection, and (b)
we dont want others poking around in
our collection, unless we let them.
31public class PictureCollection private
Picture head public Picture
getHead() return head public void
setHead(Picture head) this.head head
Now that we have an instance variable,
our instincts take over. We immediately know
that we must have accessors/modifiers for this
variable.
32public class PictureCollection private
Picture head public Picture
getHead() return head public void
setHead(Picture head) this.head head
public void insert (Picture
newPicture) if (head null)
setHead(newPicture) else insert
(newPicture, getHead())
We then code a method to insert a new Picture
reference.
33public class PictureCollection private
Picture head public Picture
getHead() return head public void
setHead(Picture head) this.head head
public void insert (Picture
newPicture) if (head null)
setHead(newPicture) else insert
(newPicture, getHead()) public void
insert(Picture newPicture, Picture current) if
(current.getNext() null)
current.setNext(newPicture) else insert
(newPicture, current.getNext())
With this code, do we end up inserting at the
beginning or end of the linked list???
34public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()null)
current.setNext(newPicture) else insert
(newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
head
Lets presume we had this structure in memory .
. .
35public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()null)
current.setNext(newPicture) else insert
(newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
head
New Item
36public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()
null) current.setNext(newPicture) else
insert (newPicture, current.getNext())
Lets trace the logic here...
We evaluate the first conditional
Data String1
Data String2
Data String3
head
New Item
37public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()
null) current.setNext(newPicture) else
insert (newPicture, current.getNext())
Lets trace the logic here...
We evaluate the first conditional
Data String1
Data String2
Data String3
head
New Item
Its not null, so we skip down to the else clause
. . .
38public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()
null) current.setNext(newPicture) else
insert (newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
head
New Item
This promotes our current to the next Picture,
and we recurse. . .
39public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()
null) current.setNext(newPicture) else
insert (newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
head
New Item
Once again, we see if the current has null next
reference . . .
40public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()null)
current.setNext(newPicture) else insert
(newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
head
New Item
Again, we skip down to the else clause, which
promotes our current
41public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()null)
current.setNext(newPicture) else insert
(newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
head
New Item
Finally, we check the conditional, and the next
is null.
42public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()null)
current.setNext(newPicture) else insert
(newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
head
New Item
So, we set the next reference to be our
newPicture reference.
43public class PictureCollection // . .
. public void insert(Picture newPicture,
Picture current) if (current.getNext()null)
current.setNext(newPicture) else insert
(newPicture, current.getNext())
Lets trace the logic here...
Data String1
Data String2
Data String3
New Item
head
Recursion unwinds, and the method finishes,
having updated our list.
44public class PictureCollection private
Picture head public Picture
getHead() return head public void
setHead(Picture head) this.head head
public void insert (Picture
newPicture) if (head null)
setHead(newPicture) else insert
(newPicture, getHead()) public void
insert(Picture newPicture, Picture current) if
(current.getNext()null) current.setNext(new
Picture) else insert (newPicture,
current.getNext())
So, this appears to work on paper. Whats
missing?
45Debug Main
So you add a debug main.
public static void main(String args)
PictureCollection pcTest new PictureCollection()
for (int i 0 i lt 5 i)
pcTest.insert (new Picture ("Test Picture "
i))
The trouble is, how do you print out whats in
the list?
We need to code a method to help with this...
46Override ( overload) toString()
public String toString() // override
toString() String strRet "Picture List\n"
return toString(getHead(), strRet) //
toString // Overload toString also private
String toString(Picture current, String strRet)
if (current ! null) strRet
current.toString() "\n" return
toString(current.getNext(), strRet) else
return strRet // toString
Note We made the overloaded method private,
since users will most likely only need to call
just the toString() method.
47We then have our test main call this toString()
method and print out whats in the test
PictureCollection
48Code Review
We just coded a set of classes to handle the
storage of Picture objects. We modeled the data
structure on a linked list, but made some design
mistakes.
A Linked List is a collection, right? Then what
is the problem?
49Code Review
Our Picture references can only hold Strings. We
cant use them to hold other object types, unless
we convert them to a String. (This is not
desirable!) What is the logical solution so that
we avoid this limitation?? Is there any issue,
penalty, or confusion that arises from that
solution?
50Generic ListNode class
- public class ListNode
-
- private Object data
- private ListNode next
-
- // etc.
51And now produce a "generic" linked list
- public class LinkedList
-
- private ListNode head
- public void add(Object data)
- // etc
- public Object removeFront()
- // etc.
52Using it...
- // Assume we have some StudentRecords
- LinkedList ll new LinkedList()
- ll.add(sr1)
- ll.add(sr2)
- ll.add(sr3)
- // we know have the slight burden of casting
being needed at times - StudentRecord student
- student (StudentRecord)(ll.removeFront())
- System.out.println(student.getName())
- System.out.println(student.getGPA())
53Now, since everything is an Object our LinkedList
can hold anything
54Including (sort of) primitives
- Primitives cannot be stored but objects from
their wrapper classes can!! - That's why we have wrapper classes!
- Each wrapper class can create an object that will
hold a primitive within it
Primitive Wrapper boolean Boolean char Character b
yte Byte short Short int Integer long Long float F
loat double Double
We can "wrap" the primitive in a wrapper and
put that object in our generic class
55Whats the big deal with linked lists?
- Linked lists are used extensively in Computer
Science - They are often used to implement stacks and
queues. - Why?
- They are also used to keep things in order
- when the number of items is small or
- performance is not too important or
- being able to move and delete items easily is
important(text editors typically use linked
lists, hence cut and paste is fast!)