Title: Implementing lists: linked implementations
1Chapter 22
- Implementing lists linked implementations
2This chapter discusses
- Linked lists
- lists built through object references.
- dynamic lists.
- linked implementations of structures more complex
than a simple sequence.
3A linked list implementation
- If the list is not empty
- there is a first element
- there is a last element
- every element (except the last) has a successor
- every element (except the first) has a
predecessor
4A linked list implementation (cont.)
- An array structure is built by creating a
reference to the collection of list elements
which are stored sequentially in memory. - A linked list is built by creating a reference to
a node of the list that, in turn contains a
reference to another node of the list, etc.
5LinkedList class
- public abstract class LinkedList implements
Cloneable -
- private class Node
- /
- Create a Node containing specified element.
- /
- public Node (Object element)
- this.element element
- this.next null
-
-
- Object element
- Node next
-
6LinkedList class (cont.)
- public abstract class LinkedList implements
Cloneable - /
- Create a Node containing specified element.
- /
- protected LinkedList ()
- size 0
- first null
-
-
- private int size
- private Node first
-
7LinkedList class (cont.)
8LinkedList class (cont.)
- The component next of the last Node always has a
value of null. - For the empty list, the LinkedList component
first is null.
9LinkedList methodsget
- public Object get (int i)
- Node p first
- int pos 0
- while (pos lt i)
- p p.next
- pos pos 1
-
- return p.element
10LinkedList methodsget (cont.)
- The variable p is initialized with a reference to
the 0-th Node of the list.
11LinkedList methodsget (cont.)
- Each iteration of the loop assigns p a reference
to the next element of the list and increments
pos.
12LinkedList methodsget (Cont).
- Loop invariant p references the Node containing
the element with index pos. - At loop termination
- pos i
- p references the Node we are looking for.
13LinkedList methodsappend
- First, find the last element of list
14LinkedList methodsappend (cont.)
- Create a new Node containing the element to be
appended - Set the old last Nodes next component to
reference the new Node. - public void append (Object obj)
- if (this.isEmpty())
- first new Node(obj)
- else
- Node p first
- while (p.next ! null)
- p p.next
- p.next new Node(obj)
-
- size size 1
-
15LinkedList methods remove
- First, find the Node in front of the one we want
to delete.
16LinkedList methods remove (cont.)
- Take next of the Node before the one to be
deleted and reference it the same as the next
field of the Node to be deleted.
17LinkedList methods remove (cont.)
- Since p.next is the Node to be deleted, p.next
cannot be null. - Removing the first element of the list is a
special case.
18LinkedList methods remove (cont.)
- public void remove (int i)
- if (i 0)
- first first.next
- else
- Node p first
- int pos 0
- while (pos lt i-1)
- p p.next
- pos pos 1
-
- p.next p.next.next
-
- size size - 1
19LinkedList methods add
20LinkedList methods add (cont.)
- public add (int i, Object obj)
- Node newElement new Node(obj)
- if (i 0)
- newElement.next first
- first newElement
- else
- Node p first
- int pos 0
- while (pos lt i-1)
- p p.next
- pos pos 1
-
- newElement.next p.next
- p.next newElement
-
- size size 1
21LinkedList methods
- get, append, remove, and add all require linear
time on average. - Deleting the first element and inserting a new
first element, are constant time operations. - We must be particularly careful of boundary
cases cases involving - the empty list
- a list with one element
- the first or last element of a list
- These may well require explicit handling.
22LinkedList variations
- A simple change will make append a constant time
operation. - We keep a reference to both the first and last
elements in the list.
23LinkedList variations (cont.)
- public append (Object obj)
- Node newElement new Node(obj)
- if (this.isEmpty())
- first newElement
- else
- last.next newElement
- last newElement
- size size 1
24LinkedList variations (cont.)
- remove must now check explicitly for the case in
which the last element is deleted. - public void remove (int i)
- if (size 1)
- // remove the only element
- first null
- last null
- else if (i 0)
- // remove the first element
- first first.next
-
25LinkedList variations (cont.)
- else
- Node p first
- int pos 0
- while (pos lt i-1)
- p p.next
- pos pos 1
-
- p.next p.next.next
- if (i size-1)
- //last element removed
- last p
-
- size size - 1
26Header nodes
- One way to eliminate special cases is to employ a
header node. - It contains no element, but is always present at
the front of the list. i.e. it is referenced by
first.
27Header nodes (cont.)
- private class Header extends Node
- public Header ()
- this.element null
- this.next null
-
-
- The LinkedList constructor creates the header.
- protected LinkedList ()
- size 0
- first new Header()
- last first
28Header nodes (cont.)
- The method append, need not check explicitly for
the empty list. - public append (Object obj)
- Node newElement new Node(obj)
- last.next newElement
- last newElement
- size size 1
-
29Circular lists
- In a circular list, the last node references the
first. - A circular list may or may not have a header.
- We can traverse the entire list starting from any
node. - Care must be taken to avoid infinite iterations
or recursions.
30Doubly-linked lists
- Each node contains references to the preceding as
well as to the following node.
31Doubly-linked lists (cont.)
- Three components
- the list elements
- references to its two neighboring nodes.
- public abstract class DoublyLinkedList implements
Cloneable - private int size
- private Node header
- private class Node
- public Node (Object element)
- this.element element
- this.next null
- this.previous null
-
- Object element
- Node next
- Node previous
-
32Doubly-linked lists (cont.)
- protected DoublyLinkedList ()
- size 0
- header new Header()
- header.next header
- header.previous header
33Doubly-linked lists (cont.)
- Operations are a bit more complicated since we
have two references in each node, but the
combination of a circular structure and a header
eliminates the need for handling most boundary
cases explicitly.
34DoublyLinkedList append
- Set previous of the new node to reference the old
last node. - Set next of the new node to reference the
header. - Set previous of the header to reference the new
node. - Set next component of the old last node to
reference the new node.
35DoublyLinkedList append (cont.)
- public void append (Object obj)
- Node newElement new Node(obj)
- Node last header.previous
- newElement.next header
- newElement.previous last
- last.next newElement
- header.previous newElement
- size size 1
36Linked list limitations
- Accessing elements by index is a linear time
operation. - The get operation is linear. Therefore, any
operation using the get method will be slower
than in an array-based implementation. - public boolean contains (List list, Object obj)
- int n list.size()
- int i 0
- while (i lt n !obj.equals(list.get(i))
- i i 1
-
- return i lt n
37Linked list limitations (cont.)
- This method can be implemented without get.
- public boolean contains (LinkedList list, Object
obj) - Node p list.first
- while (p ! null !obj.equals(p.element))
- p p.next
-
- return p ! null
-
38Dynamic storage allocation
- automatic allocation memory space for automatic
variables is allocated when the method is
invoked, and reclaimed (deallocated) when the
method completes. - Memory space for array elements is allocated when
the array is created. - For a linked implementation, space required for a
node is allocated when the node is created.
39Garbage collection
- Dynamically allocated space that can no longer be
accessed is termed garbage. - If we create an object and then loose all
references to the object, the memory space
occupied by the object becomes garbage.
40Garbage collection (cont.)
- The Java run-time system or interpreter
continuously looks for garbage and reclaims the
space (garbage collection). - Many programming languages do not include garbage
collection as part of their run-time systems. - They require programs to deallocate explicitly
dynamically allocated space. - In an object-oriented environment, it is often
difficult to know when an object no longer is
accessible.
41Garbage collection (cont.)
- Dangling references are references to space that
has been reclaimed mistakenly. - Such references result in errors that often are
extremely difficult to track down.
42Weve covered
- Linked structures
- nodes
- headers
- Doubly-linked lists
- Circular lists
- Time complexities
- Dynamic storage allocation
- garbage collection
43Glossary
44Glossary (cont.)