Linked List
Linked List
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:
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.
data for each node (the name, address, age or whatever for the items in the list), and, most importantly, a pointer to the next node. Here is the structure of a typical node:
closing curly brackets. 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!
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.
node that temp points to". When the fields of this structure are referred to, brackets can be put round the *temp part like (*temp).name, as otherwise the compiler will think we are trying to refer to the fields of the pointer. Alternatively, we can use the new pointer notation as done here. Having declared the node, we ask the user to fill in the details of the person, i.e. the name, age, address or whatever:
The last line sets the pointer from this node to the next
to NULL, indicating that this node, when it is inserted in the list, will be the last node. Having set up the information, we have to decide what to do with the pointers. Of course, if the list is empty to start with, there's no problem - just set the Start pointer to point to this node (i.e. set it to the same value as temp):
It is harder if there are already nodes in the list. In this case, the secret is to declare a second pointer, temp2,
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:
last two nodes. The full code for adding a node at the end of the list is shown below, in its own little function:
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
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.
above. It helps if you draw a diagram on paper of a linked list and work through the code using the diagram.
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
would break the chain. We need to reassign the pointers and then delete the node at the last moment. Deleting the first node in the linked list is as follows
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:
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, so print out a "No
nodes to delete" message. Make temp1 point to whatever the start pointer is pointing to. If the nxt pointer of what temp1 indicates is NULL, then we've found the last node of the list, so jump to step 7. Make another pointer, temp2, point to the current node in the list. Make temp1 point to the next item in the list. Go to step 3. 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. Delete the node pointed to by temp1. Mark the nxt pointer of the node pointed to by temp2 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:
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:
found the end node. Instead, we set the pointer temp2 to the same node as temp1
to the last node in the list, so we make temp2 point to what temp1 points to
last node in the list, with temp2 pointing to the penultimate node:
malfunction. 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:
list, with a pointer that moves backwards and forwards through the list, like an index pointer in an array. This is certainly necessary when you want to insert or delete a node from somewhere inside the list, as you will need to specify the position. We will call the mobile pointer current. First of all, it is declared, and set to the same value as the start_ptr pointer:
the address of the start pointer, as they are both pointers. The statement above makes them both point to the same thing:
It's easy to get the current pointer to point to the next node
in the list (i.e. move from left to right along the list). If you want to move current along one node, use the nxt field of the node that it is pointing to at the moment:
current = current->nxt;
item in the list. If it is, then there is no next node to move to: if (current->nxt == NULL) cout << "You are at the end of the list." << endl; Else current = current->nxt;
harder. This is because we have no way of moving back a step automatically from the current node. The only way to find the node before the current one is to start at the beginning, work our way through and stop when we find the node before the one we are considering the moment. We can tell when this happens, as the nxt pointer from that node will point to exactly the same place in memory as the current pointer (i.e. the current node).
first one. If it is, then there is no "previous" node to point to. If not, check through all the nodes in turn until we detect that we are just behind the current one.
The else clause translates as follows: Declare a temporary pointer (for use in this else clause only). Set it equal to the start pointer. All the time that it is not pointing to the node before the
current node, move it along the line. Once the previous node has been found, the current pointer is set to that node - i.e. it moves back along the list.
Now that you have the facility to move back and forth, you
need to do something with it. Firstly, let's see if we can alter the details for that particular node in the list:
directly after the current position. We have to use a temporary pointer to point to the node to be deleted. Once this node has been "anchored", the pointers to the remaining nodes can be readjusted before the node is deleted. Here is the sequence of actions:
The last step is to delete the node pointed to by temp Here is the code for deleting the node. It includes a test at the start to test whether the current node
Here is the code to add a node after the current one. This is done similarly, but it is illustrated with diagrams:
routine for adding the node to the end of the list that we created near the top of this section This routine is called if the current pointer is the last one in the list so the new one would be added to the end
Similarly, the routine get_temp(temp) is a routine that
reads in the details for the new node similar to the one defined just above
manipulating a linked list. What you should do now is string them altogether to form a coherent program. Here are some other routines that you might like to write and include in your program:
Deleting the current node in the list. Saving the contents of a linked list to a file. Loading the contents of a linked list from a file and
reconstructing it.
A doubly linked list is one where there are links from each
Each node in the list has two pointers, one to the next node
and one to the previous one - again, the ends of the list are defined by NULL pointers. Also there is no pointer to the start of the list. Instead, there is simply a pointer to some position in the list which can be moved left or right.
list is because, having moved on from one node to another, we can't easily move back So without the start pointer, we would lose track of all the nodes in the list that we have already passed With the doubly linked list, we can move the current pointer backwards and forwards
person's name. A practical list would contain more variable declarations after string name.
Assignment
Add a new node in the middle Delete a node in the middle Print the list