7.8 Using a Tail ReferenceEarlier in the chapter, we saw that new nodes can be easily added to a linked list by prepending them to the linked structure. This is sufficient when the linked list is used to implement a basic container in which a linear order is not needed, such as with the Bag ADT. But a linked list can also be used to implement a container abstract data type that requires a specific linear ordering of its elements, such as with a Vector ADT. In addition, some implementations, such as in the case of the Set ADT, can be improved if we have access to the end of the list or if the nodes are sorted by element value. The use of a single external reference to point to the head of a linked list is sufficient for many applications. In some instances, however, we may need to append items to the end of the list instead. Appending a new node to the list using only a head reference requires linear time since a complete traversal is required to reach the end of the list. Instead of a single external head reference, we can use two external references, one for the head and one for the tail. Figure 7.8.1 illustrates a sample linked list with both a head and a tail reference. Appending NodesAdding the external tail reference to the linked list requires that we manage both references as nodes are added and removed. Consider the process of appending a new node to a non-empty list, as illustrated in Figure 7.8.2 (a). First, a new node is created to store the value to be appended to the list. Then, the node is linked into the list following the last node. The If the list is empty, there is no existing node in which the link field can be adjusted. Instead, both the # Given the head and tail pointers, adds an item to a linked list. newNode = ListNode(item) if head is None : head = newNode else : tail.next = newNode tail = newNode Removing NodesRemoving a node from a linked list in which both head and tail references are used requires a simple modification to the code presented earlier in the chapter. Consider the sample list in Figure 7.8.3, in which we want to delete the node containing 21. After unlinking the node to be removed, we must check to see if it was at the end of the list. If it was, we must adjust the tail reference to point to the same node as # Given the head and tail references, removes a target from a linked list. predNode = None curNode = head while curNode is not None and curNode.data != target : predNode = curNode curNode = curNode.next if curNode is not None : if curNode is head : head = curNode.next else : predNode.next = curNode.next if curNode is tail : tail = predNode If the list contains a single node, the
|