Upload
naomi-bradford
View
218
Download
1
Embed Size (px)
Citation preview
Linked BagLinked Bag
Chapter 3Chapter 3
OutlineOutline
Pros and cons of ArrayBagPros and cons of ArrayBag Links and linked structuresLinks and linked structures Class NodeClass Node
private class Nodeprivate class Node LinkedBag MethodsLinkedBag Methods Pros and cons of LinkedBagPros and cons of LinkedBag
Pros and Cons of ArrayBagPros and Cons of ArrayBag
Pros:Pros: quick, direct access to known positionsquick, direct access to known positions fast add/remove at end of arrayfast add/remove at end of array
ConsCons fixed size fixed size oror cost of copying entries cost of copying entries slightly slower remove in middleslightly slower remove in middle wasted spacewasted space
Alternative to ArraysAlternative to Arrays
Each entry remembers who’s nextEach entry remembers who’s next bag itself remembers who’s firstbag itself remembers who’s first
Known as a “chain”Known as a “chain”
Golfer
BusinessMan
Fencer
Architect
(no one)
Doctor
Doctor
Adding to the ChainAdding to the Chain
New guy remembers who New guy remembers who waswas first first bag remembers the new personbag remembers the new person
Doctor
Golfer
BusinessMan
Fencer
Architect
(no one)
Professor
Doctor
Removing from the ChainRemoving from the Chain
From front is easyFrom front is easy reverse adding at frontreverse adding at front
Doctor
Golfer
BusinessMan
Fencer
Architect
(no one)
Professor
Doctor
Removing from the ChainRemoving from the Chain
From middle is harderFrom middle is harder find person remembering guy leavingfind person remembering guy leaving have them rememberhave them remember
the one after thethe one after theperson leavingperson leaving
Golfer
BusinessMan
Fencer
Architect
(no one)Fencer
Chains: Why? How?Chains: Why? How?
Don’t need a whole array of spacesDon’t need a whole array of spaces one extra space for each object in the bagone extra space for each object in the bag
» to remember who comes nextto remember who comes next
But the objects don’t But the objects don’t havehave extra space for extra space for remembering the following object!remembering the following object! would require an extra instance variablewould require an extra instance variable
» can’t add an extra instance variable to a String (e.g.)can’t add an extra instance variable to a String (e.g.) we need some help – a little helper classwe need some help – a little helper class
MinionsMinions
Minions remember a person and a minionMinions remember a person and a minion Gru remembers which minion comes firstGru remembers which minion comes first
Class Node (Our “Minion”)Class Node (Our “Minion”)
Remembers one object and one nodeRemembers one object and one node must be able to remember any sort of objectmust be able to remember any sort of object
» generic classgeneric class next node remembers same kind of thingnext node remembers same kind of thingpublic class Node<T> {public class Node<T> { private T data;private T data; private Node<T> next;private Node<T> next; … …}}
& &
& &
a Node
another Node
some data
more data
Class LinkedBag (Our “Gru”)Class LinkedBag (Our “Gru”)
Remembers which Node comes firstRemembers which Node comes first first node remembers the kind of thing that’s in first node remembers the kind of thing that’s in
the bag (same parameter)the bag (same parameter)public class LinkedBag<T> {public class LinkedBag<T> { private Node<T> first;private Node<T> first; private int numEntries;private int numEntries; … …}} & &
&
4
a Node
some data
a LinkedBag
LinkedBag ConstructorLinkedBag Constructor
Bag starts emptyBag starts empty no first entry, zero entriesno first entry, zero entriespublic LinkedBag() {public LinkedBag() { first = null;first = null; numberOfEntries = 0;numberOfEntries = 0;}} NOTE: no memory allocationNOTE: no memory allocation
» no need to worry about partially initialized objects!no need to worry about partially initialized objects!» no need for checkInitialization no need for checkInitialization
Linked BagLinked Bag
Bag with doctor, architect, golfer and fencerBag with doctor, architect, golfer and fencer
& &&
4
& & & & & /
Following the ChainFollowing the Chain
curNode keeps track of where we arecurNode keeps track of where we are start at first minion/node (start at first minion/node (curNode = firstcurNode = first)) go to next minion/node (go to next minion/node (curNode = curNode.nextcurNode = curNode.next))
» we know how many minions/nodes there arewe know how many minions/nodes there are
& &&
4
& & & & & /
&
curNode
/
Minions at RiskMinions at Risk
Clients should not be able to access NodesClients should not be able to access Nodes could accidentally/maliciously change valuescould accidentally/maliciously change valuescurNode.next = myBag.getFirst();curNode.next = myBag.getFirst();
& &&
4
& & & & & /
/
curNode
Private ClassesPrivate Classes
One class can actually belong to anotherOne class can actually belong to another Node can belong to LinkedBagNode can belong to LinkedBag
Can be public or privateCan be public or private private private only owner class can use it only owner class can use it owner gets owner gets full access full access either way!either way!
Declare owned class Declare owned class insideinside owner class owner classpublic class Owner {public class Owner { private class Owned {private class Owned {
Owned Generic ClassesOwned Generic Classes
Don’t need <T> on owned classDon’t need <T> on owned class owner is already <T>, so owned is, too!owner is already <T>, so owned is, too!public class LinkedNode<T> {public class LinkedNode<T> { private class Node {private class Node { private T data;private T data; // same type as bag’s base type// same type as bag’s base type private Node next;private Node next; … … }} private Node first;private Node first; private int numberOfEntries;private int numberOfEntries; … …}}
Node ConstructorsNode Constructors
Will need to create new nodesWill need to create new nodes data filled in, next maybe filled in (null if not)data filled in, next maybe filled in (null if not) code goes inside Node class inside LinkedBagcode goes inside Node class inside LinkedBagpublic Node(T value) {public Node(T value) { this(value, null);this(value, null);}}public Node(T value, Node n) {public Node(T value, Node n) { data = value;data = value; next = n;next = n;}}
/
0
Add an EntryAdd an Entry
First add:First add:
Second (and later) add:Second (and later) add:
& /
/
0
“First”
&
0
&
1
& /
“First”
&
1
“Later”
& &&
1
&
2
add(T) Methodadd(T) Method
LinkedBag method (not a Node method!)LinkedBag method (not a Node method!) create Node to remember new data valuecreate Node to remember new data value its next field is whatever its next field is whatever waswas first first
» even if there was nothing in the bag (first == null)even if there was nothing in the bag (first == null)public boolean add(T newData) {public boolean add(T newData) { first = new Node(newData, first);first = new Node(newData, first); ++numberOfEntries;++numberOfEntries; return true;return true;}}
toArray() MethodtoArray() Method
Need to make a new array & copy valuesNeed to make a new array & copy values need to follow the trail of minionsneed to follow the trail of minionspublic T[] toArray() {public T[] toArray() { T[] result = (T[]) new Object[numberOfEntries];T[] result = (T[]) new Object[numberOfEntries]; currentNode = first;currentNode = first; for (int i = 0; i < numberOfEntries; ++i) {for (int i = 0; i < numberOfEntries; ++i) { result[i] = currentNode.data;result[i] = currentNode.data; currentNode = currentNode.next;currentNode = currentNode.next; }} return result;return result;}}
Testing Core MethodsTesting Core Methods
Tests for LinkedBag are exactly the same as Tests for LinkedBag are exactly the same as for ArrayBagfor ArrayBag same methods; same behaviour expectedsame methods; same behaviour expected replace replace new ArrayBag new ArrayBag with with new LinkedBagnew LinkedBag should get same resultsshould get same results
getCurrentSize() MethodgetCurrentSize() Method
Return the number of entriesReturn the number of entriespublic int getCurrentSize() {public int getCurrentSize() { return numberOfEntries();return numberOfEntries();}} we could count the number of entrieswe could count the number of entries
» what would that code look like?what would that code look like? but why bother?but why bother?
&
4
isEmpty() MethodisEmpty() Method
Two versionsTwo versions numberOfEntries is zero:numberOfEntries is zero:public boolean isEmpty() {public boolean isEmpty() { return numberOfEntries == 0;return numberOfEntries == 0;}} first is null:first is null:public boolean isEmpty() {public boolean isEmpty() { return first == null;return first == null;}}
/
0
getFrequencyOf(T) MethodgetFrequencyOf(T) Method
Loop thru Nodes counting those equalsLoop thru Nodes counting those equalspublic int getFrequencyOf(T anEntry) {public int getFrequencyOf(T anEntry) { Node curNode = first;Node curNode = first; int count = 0;int count = 0; for (int i = 0; i < numberOfEntries; ++i) {for (int i = 0; i < numberOfEntries; ++i) { if (curNode.data.equals(anEntry)) {if (curNode.data.equals(anEntry)) { ++count;++count; }} curNode = curNode.next;curNode = curNode.next; }} return count;return count;}}
contains(T) Methodcontains(T) Method
Loop thru until find data or end of bagLoop thru until find data or end of bagpublic int getFrequencyOf(T anEntry) {public int getFrequencyOf(T anEntry) { Node curNode = first;Node curNode = first; for (int i = 0; i < numberOfEntries; ++i) {for (int i = 0; i < numberOfEntries; ++i) { if (curNode.data.equals(anEntry)) {if (curNode.data.equals(anEntry)) { return true;return true; }} curNode = curNode.next;curNode = curNode.next; }} return false;return false;}}
remove() Methodremove() Method
Reverse add method to remove first entryReverse add method to remove first entry possible problem: nothing in bagpossible problem: nothing in bagpublic T remove() {public T remove() { if (first != null) {if (first != null) { Node toDelete = first;Node toDelete = first; first = toDelete.next;first = toDelete.next; --numberOfEntries;--numberOfEntries; return toDelete.data;return toDelete.data; }} return null;return null;}}
& &
“One”
&
1
“Two”
& &&
1
&
4
&toDelete
3
clear() Methodclear() Method
Same as before!Same as before! keep removing until bag is emptykeep removing until bag is emptypublic void clear() {public void clear() { while (!isEmpty()) {while (!isEmpty()) { remove();remove(); }}}}
remove(T) Considerationsremove(T) Considerations
Remove node by updating linksRemove node by updating links links to update in node links to update in node beforebefore the one with data the one with data find the node before the node with the datafind the node before the node with the data
» but the data might not be therebut the data might not be there» but the data might be in the first nodebut the data might be in the first node
• actually, we already know how to do the first node…actually, we already know how to do the first node…• hmm.hmm.
& & & & & /removing the Golfer
Node before Golferneeds to change link
remove(T) Clever Planremove(T) Clever Plan
Find the node with the desired dataFind the node with the desired data Swap in the data from the first positionSwap in the data from the first position Remove the first node using remove()Remove the first node using remove()
& &&
4
& & & /
&
curNode
remove(T) Methodremove(T) Method
public boolean remove(T anEntry) {public boolean remove(T anEntry) { Node curNode = findNode(anEntry);Node curNode = findNode(anEntry); // private method// private method if (curNode != null) {if (curNode != null) { curNode.data = first.data;curNode.data = first.data; remove();remove(); // updates numberOfEntries// updates numberOfEntries return true;return true; }} return false;return false;} } what if the node with the data what if the node with the data isis the first node? the first node?
findNode(T) MethodfindNode(T) Method
Returns the node with the wanted dataReturns the node with the wanted data returns null if the data wasn’t foundreturns null if the data wasn’t foundprivate Node findNode(T anEntry) {private Node findNode(T anEntry) { Node curNode = first;Node curNode = first; for (int i = 0; i < numberOfEntries; ++i) {for (int i = 0; i < numberOfEntries; ++i) { if (curNode.data.equals(anEntry)) {if (curNode.data.equals(anEntry)) { return curNode;return curNode; }} curNode = curNode.next;curNode = curNode.next; }} return null;return null;}}
ExerciseExercise
Easy:Easy: Rewrite contains to use findNodeRewrite contains to use findNode
Harder:Harder: Why can’t frequencyOf use findNode?Why can’t frequencyOf use findNode? How could we change findNode so it could?How could we change findNode so it could? What changes would we need to make to What changes would we need to make to
remove(T) and contains(T) if we did?remove(T) and contains(T) if we did? Rewrite frequencyOf with the new findNodeRewrite frequencyOf with the new findNode
Pros & Cons of LinkedBagPros & Cons of LinkedBag
Pros:Pros: quick, direct access to first positionquick, direct access to first position fast add/remove at front of bagfast add/remove at front of bag little/no copying costlittle/no copying cost grows and shrinks as requiredgrows and shrinks as required
ConsCons slightly slower remove in middleslightly slower remove in middle chain requires more memory than array (!)chain requires more memory than array (!)
ArrayBag vs. LinkedBagArrayBag vs. LinkedBag
Linked grow smoothly; Array in jumpsLinked grow smoothly; Array in jumps Linked shrinks smoothly; Array doesn’tLinked shrinks smoothly; Array doesn’t Linked uses more memoryLinked uses more memory Linked slightly slower to searchLinked slightly slower to search
following links slower than incrementing indexfollowing links slower than incrementing index Add quick in bothAdd quick in both Remove quick when removing last addedRemove quick when removing last added
Next TimeNext Time
How do we tell what’s better?How do we tell what’s better?