Linked List

Linked List Containers
Linked Lists


List consists of multiple listnodes
Each listnode consists of
Data
 Pointer to another node


Traditional view of data:
Data
Data
Data
Linked Lists
FAT
MAT
RAT
HAT
Insertion at a specific point:
Get a new node (allocate from memory)
Set data pointer
Set link of new node to previous node link
Set link of previous node link to new node
Linked Lists
FAT
FAT
MAT
RAT
RAT
Deletion at a specific point:
Set the link of the previous node to the link of the
node to delete.
Linked List Representations






Can locate data in any place in memory, not
required to be sequential
No requirements on computing size of list
beforehand
No more space than need
No bounds on space
No resizing
Still fairly trivial to manage and understand
Linked Lists in C++

Need to define a ListNode Class that represents:
Data
 Pointer to another ListNode


Need to define a LinkedList Class that provides
container operations (Add, Delete, etc), using
ListNodes to implement the storage for the
container
Linked Lists in C++

Node definition:
class nodeName
{
private:
type dataName;
nodeName *link;
}
class ThreeLetterListNode
{
private:
char data[3];
ThreeLetterListNode * link;
}
Linked Lists in C++

Requirements for LinkedList construct:
Want to preserve encapsulation of nodes and ensure
that updating the data and link pointers are only
accomplished by the ListNode itself or the
LinkedList
 Arbitrary and unlimited amount of memory


Characterize the LinkedList as: A LinkedList
consists of zero or more objects of type
ListNode.
Linked Lists




Linked List definition suggests that the List object
actually physically contains lots of ListNodes.
Contains a pointer, called first, to one ListNode, from
which the rest of the ListNodes can be found by
following links.
All ListNode objects are not physically contained within
the LinkedList object
To access private data members of ListNode class,
without making the data members public or having
public functions to set data and links,

make the LinkedList class a friend of the ListNode class:
Linked Lists
class LinkedList;
// forward declaration
template <class Type>
class ListNode {
friend class LinkedList<Type>;
private:
Type data;
ListNode *link;
};
ListNode.h
template<class Type>
class LinkedList {
public: // manipulation operations
private:
ListNode<Type> *first;
}
LinkedList.h
Forward Declarations

Forward Declarations:
Used when defining classes that rely on each other.
 Indicates to compiler that the class in the forward
declaration is going to be defined later and is a valid
class.
 Similar to use of function signatures to ensure
compiler sees all available functions.

Linked Lists

Linked List Node Constructor
 Set
Data Value, Set Pointer
ListNode<Type>::ListNode<Type>(Type
inputData, ListNode<Type>* inputLink)
{
data = inputData;
link = inputLink;
}
List Operations

What operations do we want or need for the
LinkedList?
Constructor
Destructor
isEmpty()
isFull()
// doesn’t make sense in this context
add() (element?, position?)
delete() (element?, position?)
Linked Lists

Linked List Constructor
Creates an empty list
 Essence of list is “first” pointer, so that should
be set to zero if empty

LinkedList<Type>::LinkedList<Type>()
{
first = 0;
}
Linked List Insertion
Function Interface:
void add(Type & toAdd);
Passed in a variable of type Type

1st step: Generate a new ListNode
Should hold value toAdd of type Type
 Should point to nothing

Linked List Insertion

Node Creation: Node<Type> *node = new
Node<Type>(toAdd, 0);

Then need to insert in “right” place in list. What is right
place?

Depends on problem of interest
Sorted list? First in, first out list?

Let’s look at four cases:





Empty list
Non-empty, Front of list
Non-empty, Back of list
Non-empty, Arbitrary position in middle of list
Insertion into Empty List

Empty List
First
First
0
value
void LinkedList:<Type>:Add(Type & toAdd)
{
ListNode<Type> *node = new ListNode<Type>(toAdd, 0);
if (first == 0) first = node;
}
0
Insertion

Non-empty list, insert at front
first
value1
node
value3
value2
0
value1
first
0
value3
value2
0
Linked List Insertions

Insert at front method:
ListNode<Type> *node = new
ListNode<Type>(toAdd, first);
first = node;
Insertion

Non-empty list, insert at back
first
value1
node
value3
first
value2
0
0
value1
value2
value3
0
Linked List Insertions

Insert at back method:
// get to last node
ListNode<Type>* current = first;
while (current-> link != 0)
{
current = current->link;
}
// add
ListNode<Type>* node = new
current->link = node;
ListNode<Type>(toAdd, 0);
Insertion

Non-empty list, insert in middle
first
current
value1
node
value3
first
value2
0
0
value1
value3
value2
0
Linked List Insertions

Insert at arbitrary place:
ListNode<Type>* current = first;
while (someExpression holds)
// current->value < 5
{
// for example
current = current-> link;
}
ListNode<Type>* node =
new ListNode<Type>(value, current->link);
current->link = node;
Linked List Insertions

Insertion at front, insertion at end usually encapsulated
into two linked list methods:


Insert (at front), Append (onto back)
Insertion in middle could be encapsulated as
insertAtNth()

Usually seen instead as part of more complicated methods
(insertSorted for example)
Linked List: Deletion

How about deleting nodes?
Very similar to addition – 3 cases
 Case 1: Delete from front

first
value1
value2
0
value3
first
value3
value2
0
Linked Lists: Deletion

Deletion from front:
ListNode<Type>* node = first;
first = first->link;
delete node;
Linked Lists: Deletion

Case 2: Delete from back
current
first
value1
previous
value2
0
value3
first
value1
value3
0
Linked Lists: Deletion

Deletion from back:
// get to just before last node
ListNode<Type>* previous =0;
ListNode<Type>* current = first;
while (current-> link != 0)
{
previous = current;
current = current->link;
}
previous->link = 0;
delete current;
Linked Lists: Deletion

Case 3: Delete from arbitrary location
previous
first
value1
value2
current
first
value1
0
value3
value2
0
Linked Lists: Deletions
ListNode<Type>* previous =0;
ListNode<Type>* current = first;
while (someExpression holds) //current->value !=
{
// value3 for example
previous = current;
current = current->link;
}
previous->link = current->link;
delete current;
Concatenate Example


Concatenate(LinkedList<Type> listB): Add all of the
elements of a second list to the end of the first list
Three cases:




ListA is empty – Set head for listA to head of listB
ListB is empty – No change, nothing to do
Both have data – Set pointer on last node of listA to head for
listB
This version of concatenate is:


Easy to implement
Destructive towards listsA and listB – as it potentially
changes how listA and listB work from here on out (listA
delete will now cause listB nodes to go away as well)
Concatenate Example
void LinkedList<Type>::concatenate(const
LinkedList<Type> & listB)
{
// empty list A
if (!first) { first = listB.first; return; }
}
else if (listB.first) // if b is empty do nothing
{
// get to end of my list (listA)
ListNode<Type>* current = first;
while (current->link != 0) { current = current->link; }
current->link = listB.first;
}
Safer Concatenate Example
LinkedList& LinkedList<Type>::concatenate(const
LinkedList<Type> & listB)
{
// make a copy of list A using copy constructor
LinkedList returnList = *(new LinkedList(*this));
}
if (listB.first) // if b is empty do nothing, else add to end
{
ListNode<Type>* current =listB.first;
while (current->link != 0)
{
This version returns a
listA.add(current->value);
new LinkedList which is a
current = current->link;
copy of listA with copies
of listB nodes added to
}
the end. Changes to the
return returnList; }
new list don’t affect listA
or listB.