Linked Lists
Linked Lists vs. Arrays
- Limitations of arrays
- need to allocate a fixed amount of space
- need to know size ahead of time
- inserting and deleting anywhere but at the end is expensive
Linked Lists
- are an alternate data structure for storing related data
- are more complex in structure and more complex in accessing
- require the programmer to deal with the complexity
- require more overhead than arrays
- can grow and shrink in size at runtime; very efficient use of memory
- inserting and deleting is efficient anywhere in a linked list
- are not unique to C++ and are not "built-in"
What is a Linked List?
- A dynamic collection of elements called nodes; elements are usually
structs (or classes)
- Node has two main portions
- data portion -- same type of information in all nodes
- pointer to the next node in the list
- The data portion can be as simple as an int or as complex as a class
- The linked list is accessed through an external pointer called the
head which points to the first node in the list
- The last pointer in the list points to NULL, marking the end
- If the list is empty, head contains NULL
Operations on Linked Lists
- create (constructor)
- destroy (destructor)
- empty - test if empty
- length - number of elements on the list
- insert - place another element in the list
- delete - remove an element from the list
- first - get the first element in the list
- next - get the next element in the list
Linked List ADT
- We can make an ADT called a LinkedList because we have all of
the information we need.
- We know the data in the structure and we know the operations
(methods) that should be performed on the structure.
- Basically, all linked lists perform similar operations on the
list, regardless of the type of data they contain
Useful Pointers
- current - points to the most recently pointed to node
- previous - points to the node before the current node
(may be NULL if current is at the beginning)
- next - points to the node that follows the current node
(may be NULL if current is at the end)
Creating and Deleting Nodes
- use the new operator to create nodes (they will all be on the heap)
- adjust the pointers (next/previous) to keep the links correct
- when you delete an element (node) you must deallocate the
memory by using delete
- after deleting a node, adjust the nodes to keep links correct
Why not do away with arrays and use linked lists for all lists?
Step-by-Step Example
The code below refers to pictures labelled A - G.
Pictures A - E are here.
Pictures F and G are here.
struct Node
{
int data;
Node* link;
};
void main(void)
{
// Picture A
Node* head; // 1
Node* currPtr; // 2
Node* newNodePtr; // 3
// first node (Picture B)
newNodePtr = new Node; // 4
newNodePtr->data = 3; // 5
newNodePtr->link = NULL; // 6
// Picture C
head = newNodePtr; // 7
currPtr = newNodePtr; // 8
// second node (Picture D)
newNodePtr = new Node; // 9
newNodePtr->data = 6; // 10
newNodePtr->link = NULL; // 11
// Picture E
currPtr->link = newNodePtr; // 12
currPtr = newNodePtr; // 13
// third node (Picture F)
newNodePtr = new Node; // 14
newNodePtr->data = 9; // 15
newNodePtr->link = NULL; // 16
// Picture G
currPtr->link = newNodePtr; // 17
currPtr = newNodePtr; // 18
}
Example Using a Loop
struct Node
{
int data;
Node* link;
};
void main(void)
{
Node* head; // 1
Node* currPtr; // 2
Node* newNodePtr; // 3
head = new Node; // 4
head->data = 3; // 5
currPtr = head; // 6
for (int i = 2; i <= 3; i++)
{
newNodePtr = new Node;
newNodePtr->data = i * 3;
newNodePtr->link = NULL;
currPtr->link = newNodePtr;
currPtr = newNodePtr;
}
}
Comments:
- Statements 1- 3 declare the pointers
- Statements 4 - 6 set up the first node
- The loop adds new nodes and adjusts the pointers
Inserting at the Head of the List
Sometimes you want to add at the head (front) of the list rather
than at the tail (end). Notice that there is less code because we
don't need a pointer to the end of the list:
void main(void)
{
Node* head; // 1
Node* newNodePtr; // 2
head = new Node; // 3
head->data = 3; // 4
head->link = NULL; // 5
for (int i = 2; i <= 3; i++)
{
newNodePtr = new Node; // create new Node on heap
newNodePtr->data = i * 3; // set the data in the node
newNodePtr->link = head; // set next node to the head
head = newNodePtr; // make this Node the new head
}
}
This will remove a node from the head:
if (head != NULL)
{
Node* old_head = head; // save pointer to head
head = head->link; // point head to next node
delete old_head; // delete old head node
}
What data structure might this be useful for?
Back to Outline