Linked List Part 2: Implementation in Java

Overview of the Linked List Implementation

We will be using Java to implement a linked list. To achieve this, we need to create two classes: one to manage the linked list itself, including operations on the list, and another to handle the nodes (elements) within the list. Below, we provide a detailed explanation of each component of the linked list implementation.

Node Class

Each Node in the linked list contains the following components:

  • data: The value stored in the node. In our implementation, we use the integer data type, but it can be replaced with any other data type as needed.
  • next: A reference to the next node in the list, which allows traversal from one node to the next.

LinkedList Class

This class defines a singly linked list where each node contains a value and a reference to the next node in the sequence.

Fields

  • private Node head; : This is a reference to the first node in the linked list. It is null if the list is empty.
  • private Node tail; : This is a reference to the last node in the linked list. It is null if the list is empty. If size is one, head and tail will be the same.
  • private int size; : This integer keeps track of the number of nodes in the list.

Constructor

  • LinkedList(): Initializes an empty linked list with head and tail set to null, and size set to 0.

Methods

  • public int size(): Returns the current number of nodes in the linked list.
  • public Boolean isEmpty(): Returns true if the list is empty (i.e., size is 0), otherwise returns false.
  • public int get(int index): Retrieves the value of the node at the specified index.
    • Throws an IndexOutOfBoundsException if the index is out of bounds or if the list is empty.
    • Traverses the list to find the node at the given index and returns its data.
  • public Node getTail(): Returns the tail node of the list.
  • public Node getHead(): Returns the head node of the list.
  • public int[] toArray(): Converts the linked list to an array of integers.
    • Creates an integer array of size size.
    • Iterates through the linked list, copying each node's data into the array.
    • Returns the array.
  • public void addAtHead(int val): Adds a new node with the given value to the beginning of the list.
    • Creates a new node with the value val.
    • Sets the new node's next reference to the current head.
    • Updates head to point to the new node.
    • Increments size by 1.
    • Updates tail if the list was previously empty (i.e., head.next was null).
  • public void addAtTail(int val): Appends a new node with the given value to the end of the list.
    • Creates a new node with the value val.
    • If the list is empty, sets head to the new node.
    • Otherwise, sets the next reference of the current tail to the new node.
    • Updates tail to the new node.
    • Increments size by 1.
  • public void addAtIndex(int index, int val): Inserts a new node with the given value at the specified index.
    • Adds the node at the head if index is 0.
    • Adds the node at the tail if index is equal to size.
    • Throws an IndexOutOfBoundsException if the index is out of bounds.
    • Otherwise, traverses the list to find the node just before the specified index and inserts the new node at that position.
    • Increments size by 1.

Code:

```java

public class LinkedList{

    private Node head;
    private Node tail;
    private int size;

     /* Initiate empty LinkedList */
    LinkedList(){
        this.head = null;
        this.tail = null;
        this.size = 0;
    }

     /* Return the size of this linked list */
    public int size (){
        return this.size;
    }

     /* Check if the linked list is empty */
     public Boolean isEmpty (){
        return (this.size == 0);
    }

    /* Get the value of the indexth node in the linked list. */
    public int get(int index) {

        if(index >= size || index < 0 || this.head == null){
            throw new IndexOutOfBoundsException();
        }

        Node currentHead = head;

        for(int i = 0; i < index; i++){
            currentHead = currentHead.next;
        }

        return currentHead.data;
       
    }


    /* Retreive value in the tail */
    public Node getTail() {
        return this.tail;
    }

    public Node getHead(){
        return this.head;
    }

    /* Convert linked list to an array  */
    public int[] toArray(){
       
        int[] arr = new int[this.size];

        Node currentNode = this.head;
        int index = 0;

        while(currentNode != null){
            arr[index] = currentNode.data;
            currentNode = currentNode.next;
            index++;
        }

        return arr;
    }

    /*  Add a node of value val before the first element of the linked list */
    public void addAtHead(int val){

        Node newNode = new Node(val);
        newNode.next = this.head;
        this.head = newNode;
        this.size++; //increament size

        //update tail
        if(this.head.next == null){
            this.tail = this.head;
        }

    }

    /** Append a node of value val to the last element of the linked list. */
    public void addAtTail(int val){

        Node newNode = new Node (val);
        if(this.head == null){
            this.head = newNode;
        }else{
            this.tail.next = newNode;
        }
       
        this.tail = newNode;
        this.size++;

    }

    /** Append a node of value val to a given index of the linked list. */
    public void addAtIndex(int index, int val){

        if(this.size > 0 && index == 0){
            this.addAtHead(val);
            return;
        }

        if(this.size == index){
            this.addAtTail(val);
            return;
        }
       
        if(index > size || index < 0){
            throw new IndexOutOfBoundsException();
        }
       
        Node newNode = new Node (val);
        Node currentNode = this.head;
        Node prev = this.head;
        currentNode = currentNode.next;
        int count = 1;

        while(currentNode != null){

            if(count == index){
                newNode.next = currentNode;
                prev.next = newNode;
                break;

            }
            prev = currentNode;
            currentNode = currentNode.next;
            count++;
        }

        this.size++;

    }
}

What is next?

Additional operations that you can do with linked list: Deleting a Node at a Specific Index, Reversing the Linked List, and Merging Two Linked Lists. 


Top Posts

Popular Methods for Machine Learning

Big Data Characteristics Explained

Planning a Data Warehouse