Title: A Doubly Linked List
1A Doubly Linked List
Theres the need to access a list in reverse order
dnode
2Doubly Linked List Implementation
template lttypename Tgt class dnode public //
the members of a dnode object are used for
operations within a // doubly linked list
access is simplified by making them public
T nodeValue // data value of the node dnodeltTgt
prev // previous node in the list
dnodeltTgt next // next node in the list //
default constructor. creates object with value
T(), the default value // of type T. set the
node pointers to point at the node itself
dnode() // constructor with an argument to
initialize nodeValue. // set the node pointers
to point at the node itself dnode(const T
value) nodeValue(value)
3Default and Copy Constructors
Constructor creates an empty list by assigning
this to both left and right.
template lttypename Tgt dnodeltTgtdnode()
next this // the next node is the current
node prev this // the previous node is
the current node template lttypename
Tgt dnodeltTgtdnode(const T value)
nodeValue(value) next this // the
next node is the current node prev
this // the previous node is the current node
4Node Insertion
current node
prevNode
newNode
dnodeltTgt newNode, prevNode // allocate a new
node and assign prevNode to reference the
predecessor of curr newNode new dnodeltTgt(item)
prevNode curr-gtprev // update pointer
fields in newNode newNode-gtprev prevNode
newNode-gtnext curr // update curr and its
predecessor to point to newNode prevNode-gtnext
newNode curr-gtprev newNode
5The insert() Function
template lttypename Tgt dnodeltTgt insert(dnodeltTgt
curr, const T item) // declare pointer
variables for the new node and the previous
node dnodeltTgt newNode, prevNode // allocate
new dnode with item as initial value newNode
new dnodeltTgt(item) // assign prevNode the
pointer value of node before p prevNode
curr-gtprev // update pointer fields in
newNode newNode-gtprev prevNode newNode-gtnext
curr // update curr and prevNode to point at
newNode prevNode-gtnext newNode curr-gtprev
newNode return newNode
6Node Deletion Self Removal
curr
prevNode
succNode
next
next
prev
prev
dnodeltTgt prevNode curr-gtprev, succNode
curr-gtnext
prevNode -gt next succNode succNode -gt prev
prevNode
delete curr
7The erase() Function
template lttypename Tgt void erase(dnodeltTgt
curr) // return if the list is empty if
(curr-gtnext curr) return // declare
pointers for the predecessor and successor
nodes dnodeltTgt prevNode curr-gtprev, succNode
curr-gtnext // update pointer fields for
predecessor and successor prevNode-gtnext
succNode succNode-gtprev prevNode //
deallocate the memory used by the node delete
curr
8Circular Doubly Linked Lists
header
Simplify coding.
prev
An empty circular linked list
header -gt next header header-gt prev header
9Scanning a Doubly Linked List
template lttypename Tgt void writeDlinkedList(dnode
ltTgt header, const string separator )
// header points at first dnode. p moves
through the list dnodeltTgt p
header-gtnext while (p ! header)
cout ltlt p-gtnodeValue ltlt separator
p p-gtnext
10Application The Josephus Problem
11A Game Example
n 10
m 5
1
2
10
3
9
The winner!
4
8
5
7
6
12Solution to the Josephus Problem
void josephus(int n, int m) // declare the
circular doubly linked list dList and scan
pointer dnodeltintgt dList new dnodeltintgt,
curr int i, j // initialize the list of
contestants 1 2 3 ... n for (i 1 i lt n
i) insert(dList, i) // curr moves around
the list, starting at person 1 curr
dList-gtnext // delete all but one person from
the list for (i1 i lt n i) // counting
current person at curr, visit m persons. // we
must advance m-1 times. for (j1 j lt m-1
j) // advance the pointer curr
curr-gtnext
13Solution (contd)
// if curr at the header, move again if
(curr dList) curr curr-gtnext cou
t ltlt "Delete contestant " ltlt curr-gtnodeValue ltlt
endl // advance curr and erase the node we
just left curr curr-gtnext erase(curr-gtprev)
// might have deleted the rear of the list,
so // curr is now at the header. move
again if (curr dList) curr
curr-gtnext cout ltlt endl ltlt "Contestant " ltlt
curr-gtnodeValue ltlt " wins the cruise" ltlt
endl // delete the one remaining node and the
list header delete curr delete dList
14The Main Program
void main() // numContestants is number of
contestants // removeM is the rotation
selector randomNumber rnd int n, m cout ltlt
"Enter the number of contestants " cin gtgt
n // generate a random number between 1
// and numContestants m 1
rnd.random(n) cout ltlt "Generated the random
number " ltlt m ltlt
endl // solve the Josephus problem and output
the cruise winner josephus(n, m)
Enter the number of contestants? 10 Generated
the random number 5 Delete person 5 Delete
person 10 Delete person 6 Delete person 2 Delete
person 9 Delete person 8 Delete person 1 Delete
person 4 Delete person 7 Contestant 3 wins the
cruise.
15The miniList Class
Private members
dnodeltTgt header int listSize dnodeltTgt
getDNode(const T item) // allocate a dnode
dnodeltTgt dinsert(dnodeltTgt curr, const T
item) // insert before node curr and
// return address of the new node void
derase(dnodeltTgt curr) // erase node curr
from the linked list
16A Constructor
template lttypename Tgt miniListltTgtminiList(int
n, const T value) listSize(n) int i
// create an empty list header
new dnodeltTgt if (header NULL)
throw memoryAllocationError
(miniList() memory allocation
failure) // insert n copies of value at
the front of the list for (i 0 i lt n
i) dinsert(header-gtnext, value)
17Copy Constructor
template lttypename Tgt miniListltTgtminiList(const
miniListltTgt obj) listSize(obj.listSize)
// curr moves through the nodes in obj, and end
marks the finish // of a traversal through
obj dnodeltTgt curr obj.header-gtnext, end
obj.header // create an empty list
header new dnodeltTgt if (header
NULL) throw memoryAllocationError
(miniList() memory allocation
failure) // insert the values in the
linked list obj.header at the back of the current
list while (curr ! end)
dinsert(header, curr-gtnodeValue) // before
the header, i.e., back of the list
curr curr -gt next
18Iterator Nested Class
class iterator public friend class
miniListltTgt // needed by the
const_iterator constructor // that converts
a const iterator to a const_iterator friend
class const_iterator // constructor
iterator() bool operator(const
iterator rhs) const bool operator!
(const iterator rhs) const T operator
() // pointer dereference operator
iterator operator () iterator
operator (int) // postfix increment. move
forward one node iterator operator-- ()
iterator operator-- (int) private
dnodeltTgt nodePtr // pointer to the current
list node // private constructor.
converts p to an iterator // by assigning p
to nodePtr iterator(dnodeltTgt p)
nodePtr(p)
template lttypename Tgt class miniList public
// include the iterator // nested
classes include d_liter.h
private dnodeltTgt header int
listSize dnodeltTgt getDNode(
const T item) dnodeltTgt
dinsert( dnodeltTgt curr, const T
item) void derase(dnodeltTgt curr)
19Implementing Iterator Operations
T operator () // if the node's
successor is itself, the list is empty
if (nodePtr-gtnext nodePtr) throw
referenceError("miniList iterator reference
error") return nodePtr-gtnodeValue
iterator operator () nodePtr
nodePtr-gtnext // move to the successor of
nodePtr return this // return new
iterator value iterator operator (int)
// save the current value of the iterator
iterator tmp this // move to
the successor of nodePtr nodePtr
nodePtr-gtnext return tmp // return
original iterator value
20begin() and insert()
Both are member functions of class miniList.
template lttypename Tgt miniListltTgtiterator
miniListltTgtbegin() return
iterator(header-gtnext) template lttypename
Tgt miniListltTgtiterator miniListltTgtinsert(itera
tor pos, const T item) dnodeltTgt curr
pos.nodePtr, newNode // insert item
before curr and capture the new nodes address
newNode dinsert(curr, item) //
increment the list size listSize
// constructor converts newNode to an iterator
return iterator(newNode)