Link List
Link List
University of Gujrat
Before Link List
• Pointers
• Classes & objects
• Structures
• Arrays
• Memory allocation and memory
Deallocation
Disadvantage of arrays
• We must know in advance that how many elements are to be
stored in array.
• Array is static structure. It means that array is of fixed size. The
memory which is allocated to array can not be increased or
reduced.
• Since array is of fixed size, if we allocate more memory than
required then the memory space will be wasted.
• If we allocate less memory than required, then we will not be
able fit in all the elements in the array.
• The elements of array are stored in contiguous memory locations.
So insertions and deletions are very difficult and time consuming.
Wouldn’t it be great to have a list, which
is
• a dynamic data Structure.
• can grow and shrink during run time.
• easy to insert and delete.
• efficient in memory utilization, i.e. no
need to pre-allocate memory.
•
Linked Lists
A Linked List is a collection of (non-contiguous) elements
• The address of the first element is termed as the head ⋮
• Since the elements are not contiguous, each element maintains the 1358701
6 15 2nd
address of the next element. element
13587064
• The next address of the last element is 0.
• ⋮
The non-contiguous nature of memory allocation implies that the
elements may appear in any relative order in memory. 1358706
20
4 3rd
element
0
⋮
1358725
10 1st
6 element
13587016
head (13587256)
⋮
10 13587016 15 13587064 20 0 Memory
address 13587256 address 13587016 address 13587064
Going on a train ride The flag always sits on
The train can have multiple cars top of the first car
Each car may contain diferent number of people
Linked
Express
III II I
n o d e : A c o m p o u n d o b je c t th a t s to re s a re fe re n c e to a n
e le m e n t a n d a re fe re n c e , c a lle d n e x t, to a n o th e r n o d e .
E le m e n t
N ode
R e fe re n c e to a n
e le m e n t
R e fe re n c e to next
a n o th e r n o d e
Linked List
A linked list is a data structure which is built from structures
and pointers.
It forms a chain of "nodes" with pointers representing the
links of the chain and holding the entire thing together.
A linked list can be represented by a diagram as follows:
Start
NULL
This linked list has four nodes in it, each with a link to the
next node in the series.
The last node has a link to the special value NULL, which any
pointer (whatever its type) can point to, to show that it is the
last link in the chain.
There is also another special pointer, called Start, which
points to the first link in the chain so that we can keep track
of it.
head
e le m e n t e le m e n t e le m e n t e le m e n t
B a lt im o r e R om e S e a tt le T o ro n to
lin k : T h e n e x t re fe re n c e in s id e a n o d e is a lin k o r p o in te r to
a n o th e r n o d e .
W e c a n s ta rt fro m a g iv e n n o d e , a n d m o v e fro m it to th e n e x t
a n d s o o n . T h is is c a lle d lin k h o p p in g o r p o in te r h o p p in g .
head
e le m e n t e le m e n t e le m e n t e le m e n t
B a lt im o r e R om e S e a tt le T o ro n to
h e a d : T h e firs t n o d e o f a lin k e d lis t
ta il: T h e la s t n o d e o f a lin k e d lis t - it h a s a n u ll n e x t re fe re n c e .
head tail
e le m e n t e le m e n t e le m e n t e le m e n t
B a lt im o r e R om e S e a tt le T o ro n to
50B0
5110 Toronto
50A0
5100
5090
node pointer to a
50F0
5080
5070
50D0 next node
50E0 Rome
0
5070 5110
Seattle
pointer to
50D0
5060
5080
50E0 an element
Baltimore
5060 50C0
50C0
5050
50B0
5110 Toronto
50A0
5110 Toronto
50A0
5100
5090
5110 Toronto
50A0
5100
node pointer to a
5090
next node
5070 50F0
5080 50D0
5110 Toronto
50A0
5100
5090
5070 50F0
5080 50D0
50E0 Rome
0
5070 5110
Seattle
5080 50D0
5060 50E0
Baltimore
5060 50C0
50C0
5050
head
Singly Linked Lists and Arrays
Singly linked list Array
Elements are stored in linear Elements are stored in linear
order, accessible with links. order, accessible with an
index.
struct Node {
int data;
Node* next;
};
head (13587256)
data next
10 13587016 15 13587064 20 0
first last
class ListNode
{
Object data;
ListNode* next;
}
first last
class ListNode
{
Object data;
ListNode* next;
}
first last
class ListNode
{
Object data;
ListNode* next;
}
first last
class ListNode
{
Object data;
ListNode* next;
}
first last
class ListNode
{
Object data;
ListNode* next;
}
A0 A1 A2
first current
class ListNode last
{
Object element;
ListNode* next;
}
first current
last
class ListNode
{
Object element;
tmp
ListNode* next;
}
first current
x last
class ListNode
{
Object element;
tmp
ListNode* next;
}
first current
x last
class ListNode
{
Object element;
tmp
ListNode* next;
}
first current
x last
class ListNode
{
Object element;
tmp
ListNode* next;
}
A0 A1 A2
current last
class ListNode
{
Object element;
ListNode* next;
}
current->next = current->next->next;
Deleting an element
A0 A1 A2
current last
class ListNode
{
Object element;
ListNode* next;
}
A0 A1 A2
current last
Node *deletedNode = current->next;
current->next = current->next->next;
delete deletedNode;
Header Nodes
a b c
header
Header nodes allow us to avoid special cases [in the code] such
as insertion of the first element and removal of the last element.
struct node
{
char name[20]; // Name up to 20 chars
int age;
float weight;
node *nxt // Pointer to next node
};
node *start_ptr=NULL;
The important part of the structure is the line before the
closing curly brackets.
node *nxt
This gives a pointer to the next node in the list. This is the
only case in C++ where you are allowed to refer to a data
type (in this case node) before you have even finished
defining it.
A pointer called start_ptr has also been declared which will
permanently point to the start of the list.
To start with, there are no nodes in the list, which is
why start_ptr is set to NULL.
Adding a node to the end of the List
temp
undefined
We can refer to the new node as *temp, i.e. "the
node that temp points to".
if (start_ptr == NULL)
start_ptr = temp;
It is harder if there are already nodes in the list.
In this case, the secret is to declare a second pointer, temp2,
to step through the list until it finds the last node.
temp2 = start_ptr;
while (temp2->nxt != NULL)
{
temp2=temp2->nxt; //move to next node in the list
}
The loop will terminate when temp2 points to the last node
in the chain, and it knows when this happened because
the nxt pointer in that node will point to NULL.
When it has found it, it sets the pointer from that last node
to point to the node we have just declared:
temp2->nxt = temp;
NULL
The link temp2->nxt in this diagram is the link joining the
last two nodes.
The full code for adding a node at the end of the list is shown
below:
void add_node_end ( )
{ node *temp, *temp2; // temporary pointers
// reserve space for new node and fill it with data
temp=new node;
cout<< “Please enter the name of the person:”;
cin>> temp->name;
cout<< “Please enter the age of the person:”;
cin>> temp->age;
cout<< “Please enter the weight of the person:”;
cin>> temp->weight;
temp->nxt= NULL;
// set up link to this node
if (start_ptr == NULL)
start_ptr = temp;
else
{ temp2=start_ptr;
while (temp2->nxt != NULL)
{ temp2 = temp2->nxt; }
temp2->nxt = temp;
}
}
Displaying the list of nodes
Having added one or more nodes, we need to display the
list of nodes on the screen. This is comparatively easy to
do.
Here is the method:
Set a temporary pointer to point to the same thing as the start
pointer
If the pointer points to NULL, display the message "End of list"
and stop
Otherwise, display the details of the node pointed to by the
start pointer
Make the temporary pointer point to the same thing as
the nxt pointer of the node it is currently indicating
Repeat
The temporary pointer moves along the list, displaying
the details of the nodes it comes across
At each stage, it can get hold of the next node in the list
by using the nxt pointer of the node it is currently
pointing to
C++ code is as follows
temp=start_ptr;
do
{ if (temp == NULL)
cout<< “End of list “ << endl;
else
{
cout << “ Name: “ << temp->name << endl;
cout << “ Age: “ << temp ->age << endl;
cout << “ Weight: “ << temp->weight << endl;
temp = temp->nxt;
}
}
while (temp != NULL);
Check through this code, matching it to the method
listed above
It helps if you draw a diagram on paper of a linked list
and work through the code using the diagram
Deleting a Node from the List
When it comes to deleting nodes, we have three choices:
Delete a node from the start of the list
Delete one from the end of the list
Delete one from somewhere in the middle
Deleting a node from the start
We will start with deleting one from the start or from the
end
When a node is deleted, the space that it took up should be
reclaimed
Otherwise the computer will eventually run out of memory
space
This is done with the delete instruction as follows
start_ptr
NULL
temp
Now that the first node has been safely tagged (so that we can
refer to it even when the start pointer has been reassigned),
we can move the start pointer to the next node in the chain:
start_ptr = start_ptr->nxt ;
start_ptr
NULL
temp
delete temp ;
start_ptr
NULL
temp
Here if the function that deletes a node from the start of
the list
void delete_start_node ( )
{
node *temp;
temp = start_ptr;
start_ptr = start_ptr->nxt ;
delete temp;
}
Deleting a node from the end of the list is harder, as the
temporary pointer must find where the end of the list is by
hopping along from the start.
This is done using code that is almost identical to that used to
insert a node at the end of the list. It is necessary to maintain
two temporary pointers, temp1 and temp2.
The pointer temp1 will point to the last node in the list
and temp2 will point to the previous node.
We have to keep track of both as it is necessary to delete the
last node and immediately afterwards, to set the nxt pointer
of the previous node to NULL (it is now the new last node).
Look at the start pointer. If it is NULL, then the list is empty,
1. so
print out a "No nodes to delete" message.
2. Maketemp1 point to whatever the start pointer is pointing to.
3. If thenxtpointer of whattemp1 indicates is NULL, then we've
found the last node of the list, so jump to step 7.
4. Make another pointer,temp2p , oint to the current node in the
list.
5. Maketemp1point to the next item in thelist. Goto step 3.
6.If you get this far, then the temporary pointer, temp1,should
point to the last item in the list and the other temporary
pointer, temp2, should point to the second last item.
7. Delete the node pointed to bytemp1.
8. Mark thenxt pointer of the node pointed to bytemp2 as
NULL - it is the new last node.
Let's try it with a rough drawing.
This is always a good idea when you are trying to understand
an abstract data type.
Suppose we want to delete the last node from this list:
start_ptr
NULL
Firstly, the start pointer doesn't point to NULL, so we don't
have to display a "Empty list" message
Let's get straight on with step2 - set the pointer temp1 to
the same as the start pointer:
start_ptr
NULL
temp1
The nxt pointer from this node isn't NULL, so we haven't
found the end node
Instead, we set the pointer temp2 to the same node
as temp1
start_ptr
NULL
temp2 temp1
and then move temp1 to the next node in the list:
start_ptr
NULL
temp2 temp1
Going back to step 3, we see that temp1 still doesn't point
to the last node in the list, so we make temp2 point to
what temp1 points to
start_ptr
NULL
temp2 temp1
and temp1 is made to point to the next node along:
start_ptr
NULL
temp2 temp1
Eventually, this goes on until temp1 really is pointing to the
last node in the list, with temp2 pointing to the penultimate
node:
start_ptr
NULL
temp2 temp1
Now we have reached step 8. The next thing to do is to
delete the node pointed to by temp1
start_ptr
temp2 temp1
and set the nxt pointer of what temp2 indicates to NULL:
start_ptr
NULL
temp2
void delete_end_node ( )
{ node *temp1, *temp2;
if (start_ptr == NULL)
cout<<“ The list is empty” << endl;
else
{
temp1=start_ptr;
while (temp1->nxt != NULL)
{
temp2=temp1;
temp1=temp1->nxt;
}
delete temp1;
temp2->nxt=NULL;
}
}
Problem with the Code
If the list only contains one node, the code above will not
work properly.
This is because the function goes as far as the temp1 =
start_ptr statement, but never gets as far as setting
up temp2.
The code above has to be adapted so that if the first node
is also the last (has a NULL nxt pointer), then it is
deleted and the start_ptr pointer is assigned to NULL.
In this case, there is no need for the pointer temp2:
void delete_end_node ( )
{ node *temp1, *temp2;
if (start_ptr == NULL)
cout<<“ The list is empty” << endl;
else
{ temp1=start_ptr;
if (temp1->nxt==NULL)
{ delete temp1;
start_ptr=NULL;
}
else
{ while (temp1->nxt != NULL)
{ temp2=temp1;
temp1=temp1->nxt;
}
delete temp1;
temp2->nxt=NULL;
} }
}