Close
Close Window

MHC S25 COMSC 205: Data Structures

Chapter 9 Linked Lists I

«  9.1. References in Java   ::   Contents   ::   10.1. Doubly Linked Lists  »

9.2. Linked Lists

9.2.1. Nodes

In this module we present one of the two traditional implementations for lists, usually called a linked list. The linked list uses dynamic memory allocation, that is, it allocates memory for new list elements as needed. The following diagram illustrates the linked list concept. Here there are three nodes that are “linked” together. Each node has two boxes. The box on the right holds a link to the next node in the list. Notice that the rightmost node has a diagonal slash through its link box, signifying that there is no link coming out of this box.

Because a list node is a distinct object (as opposed to simply a cell in an array), it is good practice to make a separate list node class. (We can also re-use the list node class to implement linked implementations for the stack and queue data structures.) Here is an implementation for list nodes, called the Node class. Objects in the Node class contain an data field to store the element value, and a next field to store a pointer to the next node on the list. The list built from such nodes is called a singly linked list, or a one-way list, because each list node has a single pointer to the next node on the list.

class Node<E> {
    private E data;          // Value for this node
    private Node<E> next;    // Point to next node in list

    // Constructors
    public Node(E element, Node<E> nextNode) { 
        data = element;
        next = nextNode;
    
    }

    public Node(E element) { 
        data = element;
        next = null;     
    }
  
    // Return the value held in Node
    E getValue() { 
        return data; 
    }
    
    // set value held in Node
    void setValue(E newData) { 
        data = newData; 
    }            
    
    // Return next Node
    Node<E> getNext() { 
        return next; 
    }              

    // Set next Node
    void setNext(Node<E> nextNode) { 
        next = nextNode;
    } 

}

The Node class is quite simple. There are two forms for its constructor, one with an initial element value and one without. Methods allow the Node user to get or set the data and next fields.

Now, let’s take a conceptual look at a LinkedList:

Settings

Proficient Saving... Error Saving
Server Error
Resubmit

9.2.2. Linked List Partial Implementation

Now let’s look at a (partial) implementation for the linked list class, named MHCLinkedList.

Note

We’ll go over the rest of the implementation in lecture and in Lab 5!

public class MHCLinkedList<E> implements MHCList<E> {
    private Node<E> head = null;
    private Node<E> tail = null;
    private int numElements = 0;

    // Adds to the beginning of the list.
    private void addFirst(E value) {
        head = new Node<E>(value, head);
        
        if (tail == null) {
            tail = head;
        }

        numElements++;
    }

    // Adds element after the specified Node.
    private void addAfter(Node<E> node, E value) {
        Node<E> newNode = new Node<E>(value, node.getNext());
        node.setNext(newNode);
        if (tail == node) {
            tail = newNode;
        }
        numElements++;
    }

    // Find and return the node at the specified index.
    public Node<E> getNode(int index) {
        if (index < 0 || index >= numElements) {
            throw new IndexOutOfBoundsException(index);
        }

        Node<E> nextNode = head;
        for (int i = 0; i < index; i++) {
            nextNode = nextNode.getNext();
        }
        return nextNode;
    }

    // Inserts the specified element at the specified position in this list.
    public void add(int index, E value) {
        if (index < 0 || index >= numElements) {
            throw new IndexOutOfBoundsException(index);
        }

        // adding at index 0 is addFirst()
        if (index == 0) {
            addFirst (value);
        }

        // otherwise call addAfter() on index-1 node
        else {
            Node<E> prevNode = getNode(index-1);
            addAfter (prevNode, value);
        }
    }
}

9.2.3. Linked List Instance Variables

Settings

Proficient Saving... Error Saving
Server Error
Resubmit


9.2.4. addFirst() and addAfter()

In order to get to implementing the add(int position, E element) method of the List interface, it is useful to first think about how to add to the beginning of the list, and also how to add after a particular node:

Settings

Proficient Saving... Error Saving
Server Error
Resubmit

Settings

Proficient Saving... Error Saving
Server Error
Resubmit

9.2.5. Linked List Traversal and getNode()

Unlike ArrayLists, we don’t have direct access to elements at a specified index position. Instead, we have to traverse and walk down the Linked List to find the element at a position:

Settings

Proficient Saving... Error Saving
Server Error
Resubmit

9.2.6. Linked List add(int position, E element)

Putting everything together, we can implement the List add(int position, E element) method:

    // Inserts the specified element at the specified position in this list.
    public void add(int index, E value) {
        if (index < 0 || index >= numElements) {
            throw new IndexOutOfBoundsException(index);
        }

        // adding at index 0 is addFirst()
        if (index == 0) {
            addFirst (value);
        }

        // otherwise call addAfter() on index-1 node
        else {
            Node<E> prevNode = getNode(index-1);
            addAfter (prevNode, value);
        }
    }

   «  9.1. References in Java   ::   Contents   ::   10.1. Doubly Linked Lists  »

Close Window