Chapter 4 Linked Lists - PowerPoint PPT Presentation

1 / 41
About This Presentation
Title:

Chapter 4 Linked Lists

Description:

No 'random' access ... 3. The total number of elements in the list is stored in the. instance ... element selected at random by a random number generator ... – PowerPoint PPT presentation

Number of Views:126
Avg rating:3.0/5.0
Slides: 42
Provided by: markt2
Category:

less

Transcript and Presenter's Notes

Title: Chapter 4 Linked Lists


1
Chapter 4Linked Lists
  • CS 260 Data Structures
  • Indiana University Purdue University Fort Wayne

2
Linked lists
  • A linked list is a sequence of nodes in which
    each node contains a link (i.e., a reference
    variable) to the next node
  • Each node is an object consisting of info and
    the link
  • The info could be primitive data or a reference
    to another object

info link
3
Linked lists
13
head tail
7
19
null reference
Note the tail reference is optional
head tail
Empty linked list
4
Linked lists
  • Advantages
  • Memory added only incrementally
  • More flexible than an array
  • Disadvantages
  • Wastes storage for the links
  • Added complexity
  • No random access as with an array
  • Linked lists offer an attractive alternative to
    arrays in many situations

5
A class for nodes
public class IntNode private int
data private IntNode link public
IntNode( int initData, IntNode initLink )
data initData link initLink
? ? ? // end class IntNode
  • Note that this class definition is
    self-referencing
  • This is similar to recursion
  • Java allows this

6
Basic behavior of class IntNode
  • Constructor
  • getData
  • getLink
  • setData
  • setLink

7
Use of linked lists
  • Build and output a linked list containing the
    integers 1, 2, 3, , 100

IntNode head null IntNode tail
null head new IntNode( 1, head ) tail
head for ( int i 2 i lt 100 i ) head
new IntNode( i, head )
1
head tail
2
head tail
1
100
head tail
99
98
3
2
1
? ? ?
8
Output of the linked list
for ( IntNode cursor head cursor ! null
cursor cursor.getLink() )
System.out.println( cursor.getData() )
100
head tail
99
98
3
2
1
? ? ?
  • This statement outputs the values in the linked
    list in the order 100, 99, 98, , 3, 2, 1
  • The list was built by adding new nodes to the
    head
  • But how could we build the list so that the
    values are output is in the order created?
  • Build the list by adding new nodes to the tail

9
Build the list by adding to the tail
IntNode next head new IntNode( 1, null ) tail
head for ( int i 2 i lt 100 i )
next new IntNode( i, null ) tail.setLink(
next ) tail next
1
head tail
1
head tail
2
next
1
head tail
2
3
98
99
100
? ? ?
next
10
Enhancing class IntNode
  • We have been working from outside the IntNode
    class
  • Need methods getData, setLink, etc.
  • It is better to add useful operations to IntNode
    that work from the inside

11
Method addNodeAfter
public IntNode addNodeAfter( int element )
link new IntNode( element, link ) return
link
Note Method returns a pointer to the node added,
in contrast to a similar text method (page 179)
Insert an IntNode containing 23 after the node
referenced by p p.addNodeAfter( 23 )
p
17
11
81
3
? ? ?
? ? ?
23
12
Build the list again using the new method
IntNode next head new IntNode( 1, null ) tail
head for ( int i 2 i lt 100 i )
tail tail.addNodeAfter( i )
1
head tail
1
head tail
2
1
head tail
2
3
98
99
100
? ? ?
13
Method removeNodeAfter
public IntNode removeNodeAfter( ) link
link.link
  • Note there is a distinction between link. and
    link
  • Link is the primitive reference variable
  • Link. is the object link refers to !

p
p.removeAfter()
link.
link
17
11
81
3
? ? ?
? ? ?
14
Method removeNodeAfter
  • To use removeNodeAfter, a reference to a node
    just before the node to be removed must be set up
  • The removed node becomes inaccessible
  • (unless, of course, an alias has been made of
    the node)
  • Garbage collection
  • A Java run-time system periodically finds and
    recycles inaccessible storage
  • Caution tail.removeNodeAfter causes a
    NullPointerException()

15
Static methods for the IntNode class
  • There are 6 static methods
  • listCopy
  • listCopyWithTail
  • listLength
  • listPart
  • listPosition
  • listSearch
  • Each of these operates on an entire list
  • They would be more properly implemented as
    instance methods in a new IntList class having
    entire lists as objects

16
Usage of the static methods
n IntNode.listLength( head ) // returns
the size of the list
newList IntNode.listCopy( head ) // Clones the
list and returns a pointer to the clone
selection IntNode.listSearch( head, 19 ) //
Searches the list starting with head for a node
containing 19 // Returns a pointer to the node
if successful, otherwise returns null
selection IntNode.listPosition( head, 19 ) //
Searches the list starting with head for a node
at position 19 // Returns a pointer to the node
if successful, otherwise returns null //
Position numbers start with 1, not 0
17
Static methods for the IntNode class
  • listCopyWithTail and listPart both return two
    pointers
  • References to both the head and tail of a list
  • How?
  • Return a 2-cell array copyInfo
  • copyInfo 0 refers to the head
  • copyInfo 1 refers to the tail

18
Usage of the static methods
  • IntNode copyInfo
  • copyInfo IntNode.listCopyWithTail( head )
  • // Clones the list and returns head and tail
    pointers to the clone
  • // copyInfo 0 points to the head of the clone
  • // copyInfo 1 points to the tail of the clone
  • IntNode copyInfo
  • copyInfo IntNode.listPart( startNode,
    finishNode )
  • // Clones the part of the list from startNode to
    finishNode
  • // startNode and finish node must be nodes in the
    list
  • // startNode must preceed finishNode
  • // Returns head and tail pointers to the cloned
    part
  • // copyInfo 0 points to the head of the clone
  • // copyInfo 1 points to the tail of the clone

19
Methods listLength and listSearch
public static int listLength( IntNode head )
IntNode cursor int answer
answer 0 for ( cursor head cursor
! null cursor cursor.link )
answer return answer
Note there is a trade-off in not having an
instance variable like manyItems
public static IntNode listSearch( IntNode head,
int target ) IntNode cursor for (
cursor head cursor ! null cursor
cursor.link ) if ( target cursor.data
) return cursor return null

20
Method listPosition
public static IntNode listPosition( IntNode head,
int position ) IntNode cursor int
i if ( position lt 0 )
throw new IllegalArgumentException( "position is
not positive ) cursor head for (
i 1 ( i lt position ) ( cursor ! null )
i ) cursor cursor.link return
cursor
This method returns null if position is beyond
the end of the list
21
Method listCopy
public static IntNode listCopy( IntNode source )
IntNode copyHead IntNode
copyTail if ( source null )
return null copyHead new
IntNode( source.data, null ) copyTail
copyHead while ( source.link ! null )
source source.link copyTail
copyTail.addNodeAfter( source.data )
return copyHead
22
Method listCopyWithTail
public static IntNode listCopyWithTail(
IntNode source ) IntNode copyHead
IntNode copyTail IntNode answer new
IntNode 2 if ( source null )
return null copyHead new
IntNode( source.data, null ) copyTail
copyHead while ( source.link ! null )
source source.link copyTail
copyTail.addNodeAfter( source.data )
answer 0 copyHead answer 1
copyTail return answer
23
Method listPart
public static IntNode listPart( IntNode start,
IntNode end ) IntNode copyHead
IntNode copyTail IntNode answer new
IntNode 2 if ( start null )
throw new IllegalArgumentException( start is
null ) if ( end null ) throw
new IllegalArgumentException( end is null )
copyHead new IntNode( start.data, null )
copyTail copyHead while ( start !
end ) start start.link if
( start null ) throw new
IllegalArgumentException( end node was not found
on the list ) copyTail
copyTail.addNodeAfter( start.data )
answer 0 copyHead answer 1
copyTail return answer
24
Applications of linked lists
  • Our applications are to develop bag and sequence
    classes using linked lists instead of arrays
  • IntLinkedBag
  • DoubleLinkedSeq
  • In each case, the data structure should appear to
    be essentially the same to the user
  • The goal is to allow an application to use the
    new implementation by only changing the name of
    the class being used
  • Names of methods should not change

25
Class IntLinkedBag
  • This is the bag ADT implemented with a linked
    list
  • See text pages 208 225 for details
  • State
  • private IntNode head
  • private int manyNodes
  • ADT invariant of the IntLinkedBag class (see
    textbook, p. 212)
  • The elements of the bag are stored in a linked
    list.
  • The head reference of the list is stored in the
    instance
  • variable head.
  • 3. The total number of elements in the list is
    stored in the
  • instance variable manyNodes

26
Class IntLinkedBag
  • Behavior summary
  • Eliminate methods
  • getCapacity
  • ensureCapacity
  • trimToSize
  • These have nothing to do with a bag as an ADT
  • Should these have been included in IntArrayBag?
  • New method grab
  • grab returns an element selected at random by a
    random number generator
  • Could grab have been included in IntArrayBag?

27
Class IntLinkedBag
  • Note that there is trade-off in including the
    instance variable manyNodes
  • Without a partially-filled array, something like
    manyItems is no longer needed
  • The static method listLength(? ? ?) could be used
    to implement the size( ) method
  • This would simplify the ADT invariant for the
    class
  • But on the other hand, O( size ) is then linear
    rather than constant

28
Class IntLinkedBag
  • Constructor
  • Method add
  • Since order is not important, new elements may be
    added at the head of the list

public IntLinkedBag( ) head null
manyNodes 0
public void add( int element )
head new IntNode( element, head )
manyNodes
29
Method remove
public boolean remove( int target )
IntNode targetNode // The node that contains
the target targetNode IntNode.listSearch(
head, target ) if ( targetNode null
) // The target was not found return
false else // The target was found at
targetNode // Copy the head data to
targetNode and then remove the extra copy
targetNode.setData( head.getData( ) )
head head.getLink( ) manyNodes--
return true
30
Method remove
  • Just after IntNode.listSearch
  • After return

manyNodes head targetNode
5
19
target
33
11
19
92
56
4
19
manyNodes head targetNode
target
33
11
33
92
56
31
Method remove
  • Does it work if the head element, 33, is removed?
  • Boundary case

4
33
manyNodes head targetNode
target
33
11
19
92
56
32
Method addAll
public void addAll( IntLinkedBag addend )
IntNode copyInfo // The node that
will refer to the target if ( addend
null ) throw new IllegalArgumentException
( Addend is null. ) if (
addend.manyNodes gt 0 ) copyInfo
IntNode.listCopyWithTail( addend.head )
copyInfo1.setLink( head ) // Link the tail
of copy to my own head... head
copyInfo 0 // and set my own
head to the head of the copy. manyNodes
manyNodes addend.manyNodes
33
Method addAll
  • Perform a.allAll( b ) for bags a and b
  • The addend bag is b

10
20
30
a.head
40
50
b.head
copyInfo
40
50
O 1
34
Class DoubleLinkedSeq
  • This is the sequence ADT implemented with a
    linked list
  • See text pages 225 231
  • State
  • private DoubleNode head
  • private DoubleNode tail
  • private DoubleNode cursor
  • private DoubleNode precursor
  • private int manyNodes

35
Class DoubleLinkedSeq
33
11
19
92
56
head tail cursor
precursor manyNodes
5
  • The precursor always points to the node just
    before the cursor

36
Class DoubleLinkedSeq
  • ADT invariant of the DoubleLinkedSeq class
  • The elements of the sequence are stored in a
    linked list
  • The total number of elements in the list is
    stored in the instance variable manyNodes
  • If the list is not empty, head refers to the
    first element in the list otherwise it is the
  • null reference
  • 4. If the list is not empty, tail refers to the
    last element in the list otherwise, it is the
  • null reference
  • 5. If there is a current element, that element is
    referred to by cursor
  • otherwise, cursor is the null reference
  • 6. If there is a current element and it is not
    the first element, then precursor refers to the
  • element just before the current element,
    otherwise precursor is the null reference
  • 7. When a new element is added, it becomes the
    new current element
  • 8. When an element is removed or advance is
    applied, the following element is current
  • if no following element exists, there is no
    current element

37
A DoubleLinkedSeq method
  • Recall . . .
  • Method addBefore adds a new element to a sequence
  • If there is a current element, addBefore places
    the new element before the current element
  • If there is no current element, addBefore places
    the new element at the front of the sequence
  • The new element always becomes the new current
    element of the sequence

38
Method addBefore
public void addBefore( double element )
if ( ( precursor null ) // either no
current element or current element is first
// add element to the head of the list
head new IntNode( element, head )
cursor head else
// cursor
points to the middle of the list
precursor.setLink( new IntNode( element, cursor )
) cursor precursor.getLink()
if ( manyNodes 0 ) // the
list was empty and tail needs to be initialized
tail head manyNodes
  • Is precursor OK when adding at head?
  • Is tail OK when cursor tail?

39
Beyond simple linked lists
  • Doubly-linked lists
  • Nodes have two pointers
  • Doubly-linked lists have the form . . .

backLink data foreLink
33
19
23
87
head
40
Beyond simple linked lists
  • Dummy list heads
  • List head is never null
  • Empty linked list
  • Methods may often be simplified using dummy list
    heads
  • Example Inserting an element at the logical
    beginning of a list is the same as inserting the
    element in the middle of the list
  • A dummy list heads may be used in conjunction
    with a doubly-linked list


11
19
92
56
head
dummy

head
dummy
41
Linked list and array trade-offs
Write a Comment
User Comments (0)
About PowerShow.com