Analysis of Algorithms

6.2 Node Lists
© 2004 Goodrich, Tamassia
Node-Lists
1
Using an index is not the only means of
referring to the place where an element
appears in a list (sequence).
If we have a list S implemented with a (singly
or doubly) linked list, then it’s natural to use a
node instead of an index to identify where to
access and update S.
We’ll define the node list ADT, which abstracts
the concrete linked list data structure using a
position ADT that abstracts the notion of
“place” in a node list.
© 2004 Goodrich, Tamassia
Node-Lists
2
6.2.1 Node-Based Operations
Assuming List S be implemented using (singly or
doubly) linked list.
We would like to define methods for S that take
nodes as parameters and provide nodes as return
types.
For instance, we could define a method remove (v)
that removes the element of S at node v of the list.
This could be executed in O(1) time, by simply
“linking out” this node by updating next and prev links
of its neighbors.
© 2004 Goodrich, Tamassia
Node-Lists
3
Similarly, we could insert, in O(1) time, a new element e into S
with an operation such as addAfter(v,e), that specifies the node v
after which the node of the new element should be inserted. In
this case, we simply “linking in” this new node.
By defining methods of a list ADT by adding such node-based
operations requires much more information about the
implementation of our list.
Certainly, it’s desirable to be able to use either a singly or doubly
linked list, without revealing this detail to a user.
To abstract and unify the different ways of storing elements in
the various implementations of a list, we introduce the concept
of “position”, which formalizes the notion of “place” of an
element relative to others in the list.
© 2004 Goodrich, Tamassia
Node-Lists
4
6.2.2 Position ADT
So as to safely expand the set of operations
for lists, we abstract a notion of “position”
that allows us to enjoy the efficiency of
doubly or singly linked list implementation,
without violating “object-oriented” design
principles.
We view a list as a “collection of elements”
that stores each element at a position and
that keeps these positions arranged in a
linear order.
© 2004 Goodrich, Tamassia
Node-Lists
5
Position ADT
The Position ADT models the notion of
place within a data structure where a
single object is stored
It supports just one method:

object element(): returns the element
stored at this position
© 2004 Goodrich, Tamassia
Node-Lists
6
Properties of Position ADT
A position is always defined relatively, that is in terms of its
neighbors.
In a list, a position p will always be “after” some position q and
“before” some position s (unless p is the first or last position).
A position p, which is associated with some element e in a list S,
does not change even if the index of e changes in S, unless we
explicitly remove e (and, hence, destroy position p).
Moreover, the position p does not change even if we replace or
swap the element e stored at position p with another element.
© 2004 Goodrich, Tamassia
Node-Lists
7
6.2.3 Node List ADT
Using the concept of position to encapsulate the idea of
“node” in a list, we can define another type of sequence (list)
ADT, called node list ADT.
The node list ADT models a sequence of positions storing
arbitrary objects.
It establishes a before/after relation between positions.
1. Generic methods:
 size(), isEmpty()
© 2004 Goodrich, Tamassia
Node-Lists
8
2. Accessor Methods
This Node List ADT supports the following methods for accessing
elements in a list S : (All these methods return type position)
 first():Return the position of the first element of S; an error
occurs if S is empty.
 last():Return the position of the last element of S; an error
occurs if S is empty.
 prev(p):Return the position of the element of S preceding the one
at position p; an error occurs if p is the first position.
 next(p):Return the position of the element of S following the one
at position p; an error occurs if p is the last position.
The above methods allow us to refer to relative positions in a
list, starting at the start or end, and to move incrementally up or
down the list S.
© 2004 Goodrich, Tamassia
Node-Lists
9
3. Update Methods
In addition to the accesor methods and the generic methods,
we also include the following update methods for the node list
ADT, that take position objects as parameters and/or provide
position object in return values:
 set(p,e): Replace the element at position p with e, returning the
element formerly found at position p.
 addFirst(e): Insert a new element e into S as the first element.
 addLast(e): Insert a new element e into S as the last element.
 addBefore(p,e): Inserts a new element e into S before position p.
 addAfter(p,e): Inserts a new element e into S after position p.
 remove(p): Remove and return the element at position p in S,
invalidating this position p in S.
© 2004 Goodrich, Tamassia
Node-Lists
10
The node list ADT allows us to view an
ordered collection of objects (list) in terms of
their places, without worrying about the exact
way those places are represented (or,
implemented). See Figure below.
Baltimore
New York
p
q
Paris
r
Providence
s
Figure 6.1: A node list. The positions in the current order are p, q, r, and s.
© 2004 Goodrich, Tamassia
Node-Lists
11
No Redundancy
They may at first seem to be redundancy in the
above set of operations for the node list ADT, since
we can perform operation:

addFirst(e) with addBefore(first(),e), and

addLast(e) with addAfter(last(),e).
But these substitutions can only be done
for nonempty list.
© 2004 Goodrich, Tamassia
Node-Lists
12
Error Conditions
Note that an error condition occurs if a position
passed as argument to one of the list operations
(methods) is invalid. Reasons for a position p to be
invalid include:

p = null

p was previously removed from the list

p is a position of a different list

p is the first position of the list and we call prev(p)

p is the last position of the list and we call next(p).
© 2004 Goodrich, Tamassia
Node-Lists
13
Example 6.2
We show a series of operations for an initially empty list node S. We
use variables p1 , p2 and so on, to denote different positions, and we
show the object currently stored at such a position in parentheses.
Operation
Output
S
isEmpty()
true
(-)
last()
error
(-)
addFirst(8)
-
(8)
first()
p1 (8)
(8)
addAfter(p1 ,5)
-
(8,5)
next(p1)
p2 (5)
(8,5)
addBefore(p2 ,3)
-
(8,3,5)
prev(p2)
P3 (3)
(8,3,5)
addFirst(9)
-
(9,8,3,5)
last()
p2 (5)
(9,8,3,5)
remove(first())
9
(8,3,5)
Set(P3,7)
3
(8,7,5)
addAfter(first(),2)
-
(8,2,7,5)
Size()
4
(8,2,7,5)
© 2004 Goodrich, Tamassia
Node-Lists
14
Applications of Node List ADT
The node list ADT, with its built-in notion of position, is useful in
a number of settings. Following are two examples:
a program that simulates a game of cards could model each
person’s hand as a node list. Inserting and removing cards from a
person’s hand could be implemented using the methods of the
node list ADT, with the positions being determined by the
ordering of cards in the suit.
a simple text editor embeds the notion positional insertion
and removal relative to a cursor, that represents the current
position in the list of characters of text being edited.
© 2004 Goodrich, Tamassia
Node-Lists
15
Implementing (Array list) Vector ADT with Node-List ADT
Vector ADT:
List ADT:

size() and isEmpty()


get(integer i)



first(), last()
prev(p), next(p)

set(p, e)
set(integer i, object e)

insertBefore(p, e)
insertAfter(p, e)
insertFirst(e)
insertLast(e)

remove(p)


add(integer i, object e)



remove(integer i)
© 2004 Goodrich, Tamassia
Node-Lists
size(), isEmpty()
16
Node List ADT Exceptions
An interface for the node list ADT uses the following
exceptions to indicate error conditions:
BoundaryViolationException: Thrown if an attempt is
made to access an element whose position is outside
the range of positions of the list, (ex., calling next on
the last position).
InvalidPositionException: Thrown if a position provided
as argument in invalid, (ex., it is null or it has no
associated list).
© 2004 Goodrich, Tamassia
Node-Lists
17
6.2.4 Doubly Linked List Implementation
A doubly linked list provides a natural
implementation of the List ADT
Nodes implement position ADT and store:

element

link to the previous node

link to the next node
Special trailer and header sentinel nodes
Nodes thus define a method element that return
the element stored at the node
prev
next
elem
nodes/ positions
header
node
trailer
elements
© 2004 Goodrich, Tamassia
Node-Lists
18
Insertion
We visualize operation addAfter(p, X), which returns position q
p
A
B
C
p
A
q
B
C
X
p
A
© 2004 Goodrich, Tamassia
q
B
Node-Lists
X
C
19
Insertion Algorithm
Algorithm addAfter(p,e):
Create a new node v
v.setElement(e)
v.setPrev(p)
{link v to its predecessor}
v.setNext(p.getNext()) {link v to its successor}
(p.getNext()).setPrev(v) {link p’s old successor to v}
p.setNext(v)
{link p to its new successor, v}
return v {the position for the element e}
© 2004 Goodrich, Tamassia
Node-Lists
20
Deletion
We visualize remove(p), where p = last()
p
A
B
C
A
B
C
D
p
D
A
© 2004 Goodrich, Tamassia
B
Node-Lists
C
21
Deletion Algorithm
Algorithm remove(p):
t = p.element() {a temporary variable to hold the
return value}
(p.getPrev()).setNext(p.getNext())
{linking out p}
(p.getNext()).setPrev(p.getPrev())
p.setPrev(null) {invalidating the position p}
p.setNext(null)
return t
© 2004 Goodrich, Tamassia
Node-Lists
22
Performance
In the implementation of the Node List ADT
by means of a doubly linked list, we conclude
the following:





The space used by a list with n elements is O(n)
The space used by each position of the list is O(1)
All the methods of the Node List ADT run in O(1)
time
Operation element() of the
Position ADT runs in O(1) time
Thus, a doubly linked list is an efficient
implementation of the Node List ADT
© 2004 Goodrich, Tamassia
Node-Lists
23