Chapter 17
Linked Lists:
Doubly Linked Lists
© Pearson Education Limited 2015
WHAT IS A LINKED LIST?
A linked list
Zero or more nodes linked to one another as follows:
5
15
25
NULL
head
Every node stores
A data element
A pointer to the next node (ListNode * next)
List has a ListNode*
head to point to first node
Last node must point to NULL
© Pearson Education Limited 2015
VARIATIONS OF THE LINKED LIST
Linked lists come in different flavours
One example is a doubly linked list
Each node contains two pointers
One to the next node in the list
One to the previous node in the list
prev
next
5
head
NULL
13
next
prev
© Pearson Education Limited 2015
19
NULL
VARIATIONS OF THE LINKED LIST
How is a doubly linked list better?
Traversal in either direction is possible
In addition to a head, store a tail (pointer to the last node)
For complex operations such as insertion and
deletion, no extra previous node pointer is required
prev
next
5
head
NULL
13
next
prev
© Pearson Education Limited 2015
19
NULL
DOUBLY LINKED LIST: TEMPLATE
template <class T>
class DoublyLinkedList
{
private:
struct ListNode // node structure
{
T value;
// the value in this node
ListNode* next; // address of next node
ListNode* prev; // address of previous node
ListNode(T nodeValue) : value(nodeValue) {
next = NULL;
prev = NULL;
}
};
ListNode* head;
ListNode* tail;
// list head pointer
// list tail pointer
// the rest of the class functions go here
};
© Pearson Education Limited 2015
Singly linked list: Appending a Node of type T
template <class T>
void LinkedList<T>::appendNode(T num)
{
ListNode* newNode; // to point to a new node
ListNode* nodePtr; // to move through the list
newNode = new ListNode(num);
if (!head) // if head is null
head = newNode; // both are pointers
else // otherwise, insert newNode at end.
{
nodePtr = head;
// find the end of the list
while (nodePtr->next) { // while next != 0
nodePtr = nodePtr->next;
}
How do we
nodePtr->next = newNode;
change this for
}
doubly linked
list?
}
© Pearson Education Limited 2015
Doubly Linked List: Appending a Node of type T
template <class T>
void DoublyLinkedList<T>::appendNode(T num)
{
ListNode* newNode; // to point to a new node
ListNode* nodePtr; // to move through the list
newNode = new ListNode(num);
1. Update tail as well
if (!head)
as the head
{
head = newNode;
tail = newNode;
}
else // Otherwise, insert newNode at the end
{
tail->next = newNode;
2. Instead of iterating, go
newNode->prev = tail;
directly to the last element
tail = newNode;
}
}
3. Update the previous pointer
of newNode and the tail
© Pearson Education Limited 2015
Singly Linked List: Inserting a Node of Type T
template <class T>
void LinkedList<T>::insertNode(T num)
{
ListNode *newNode; // to point to a new node
ListNode *nodePtr; // to move through the list
ListNode *prevNode; // to store prev. node position
newNode = new ListNode(num); // dynamically allocate
if (!head){ // if head is null
head = newNode; // both are pointers
newNode->next = NULL;
}
else // otherwise, insert newNode at correct position
{
nodePtr = head;
while (nodePtr!=NULL && nodePtr->value < num)
{
prevNode = nodePtr;
nodePtr = nodePtr->next;
}
© Pearson Education Limited 2015
Singly Linked List: Inserting a Node of Type T
if (prevNode == NULL) // will be 1st node in list
{
head = newNode;
newNode->next = nodePtr;
}
else // otherwise, insert newNode at correct pos
{
prevNode->next = newNode;
newNode->next = nodePtr;
}
}
}
Let’s update this algorithm to work for a doubly
linked list!
© Pearson Education Limited 2015
Doubly Linked List Insert: Searching for Correct Place
nodePtr
We must find
the successor
Insert
15
NULL
prev
next
next
5
13
head
No need to
store previous
address – it’s
already stored
by each node!
next
19
tail
prev
NULL
15
NULL
newNode
NULL
nodePtr = head;
while (nodePtrWhich
!= NULL
&& nodePtr->value
newValue)
pointers
must we update to<insert
15?
{
nodePtr = nodePtr->next;
}
© Pearson Education Limited 2015
Doubly Linked List Insert: Attaching the Node
nodePtr
NULL
prev
next
next
5
13
head
19
tail
prev
null
15
NULL
newNode
NULL
nodePtr->prev->next = newNode;
© Pearson Education Limited 2015
Doubly Linked List Insert: Attaching the Node
nodePtr
NULL
prev
next
next
5
13
head
null
19
tail
prev
prev
15
NULL
newNode
newNode->prev = nodePtr->prev;
© Pearson Education Limited 2015
Doubly Linked List Insert: Attaching the Node
nodePtr
NULL
prev
next
next
5
13
head
null
19
prev
prev
15
newNode
newNode->next = nodePtr;
© Pearson Education Limited 2015
tail
Doubly Linked List Insert: Attaching the Node
nodePtr
NULL
prev
next
next
5
13
head
null
19
prev
prev
15
newNode
nodePtr->prev = newNode;
© Pearson Education Limited 2015
tail
Doubly Linked List: Inserting a Node of Type T
template <class T>
void DoublyLinkedList<T>::insertNode(T newValue) {
ListNode *newNode, *nodePtr = NULL;
newNode = new ListNode(newValue);
if (!head) { // if list is empty
head = newNode;
tail = newNode;
}
else // Otherwise, insert newNode
{
nodePtr = head;
// Skip nodes whose value is less than newValue
while (nodePtr != NULL && nodePtr->value < newValue)
{
nodePtr = nodePtr->next;
}
© Pearson Education Limited 2015
if (!nodePtr) // if new node is to be last node
{
tail->next = newNode;
newNode->prev = tail;
tail = newNode;
}
// If the new node is to be the 1st in the list,
// insert it before all other nodes
else if (nodePtr->prev == NULL) {
newNode->next = nodePtr;
nodePtr->prev = newNode;
head = newNode;
}
else // Otherwise, insert it after the prev node
{
nodePtr->prev->next = newNode;
newNode->prev = nodePtr->prev;
newNode->next = nodePtr;
nodePtr->prev = newNode;
}
}
}
© Pearson Education Limited 2015
HOW WOULD YOU DELETE FROM A
DOUBLY LINKED LIST?
NULL
5
NULL
head
NULL
Delete from the head?
13
next
prev
19
tail
When would this fail?
When the list is empty (head is NULL)
head = head->next;
delete head->prev;
head->prev = NULL;
When the list contains one element
(head->next == NULL)
© Pearson Education Limited 2015
HOW WOULD YOU DELETE FROM A
DOUBLY LINKED LIST?
NULL
5
13
head
NULL
Delete from the tail?
next
prev
19
NULL
tail
When would this fail?
When the list is empty (tail is NULL)
tail = tail->prev;
delete tail->next;
tail->next = NULL;
When the list contains one element
(tail->prev == NULL)
© Pearson Education Limited 2015
HOW WOULD YOU DELETE FROM A
DOUBLY LINKED LIST? nodePtr
null
5
13
next
19
prev
head
null
Delete from the middle?
nodePtr->prev->next = nodePtr->next;
nodePtr->next->prev = nodePtr->prev;
delete nodePtr;
© Pearson Education Limited 2015
tail
DOUBLY LINKED LIST
Are doubly linked lists better than singly linked lists?
Yes, if
You often insert at the front and at the end
You often traverse front to back and back to front
Which one is more efficient in terms of memory use?
© Pearson Education Limited 2015
SUMMARY
Doubly linked lists are bi-directional linked lists
Two new variables are introduced
A prev pointer added to each node
A tail pointer added to the linked list class
Singly-linked list algorithms are modified
They must now take care of the prev and tail pointers
Next lecture: Circular linked list
© Pearson Education Limited 2015