Java Singly Linked List Implementation

A Singly Linked List is a fundamental data structure consisting of nodes where each node contains data and a reference to the next node.

Defining the Node Class

The Node class is the building block of the list, containing the data and the pointer to the next element.

class Node {
    private String data;
    private Node next;

    public Node(String data) {
        this.data = data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public void setNext(Node node) {
        this.next = node;
    }

    public String getData() {
        return this.data;
    }

    public Node getNext() {
        return this.next;
    }
}

The LinkedList Class Structure

The LinkedList class manages the head and tail pointers and provides methods for list manipulation.

class LinkedList {
    private Node head;
    private Node tail;

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

    public Node getTail() {
        return this.tail;
    }

Adding Nodes to the List

New elements can be added at the end or the beginning of the list.

    public void addAtEnd(String data) {
        // Create a new node
        Node node = new Node(data);

        // Check if the list is empty,
        // if yes, make the node the head and the tail
        if (this.head == null)
            this.head = this.tail = node;
        else {
            // If the list is not empty, add the element at the end
            this.tail.setNext(node);
            // Make the new node the tail
            this.tail = node;
        }
    }

    public void addAtBeginning(String data) {
        // Create a new node
        Node node = new Node(data);

        // Check if the list is empty
        if (this.head == null)
            this.head = this.tail = node;
        else {
            // Add the element at the beginning
            node.setNext(this.head);
            this.head = node;
        }
    }

Displaying and Finding Nodes

Traversal is used to print the list or search for specific data.

    public void display() {
        Node temp = this.head;

        // Traverse the list and print each node
        while (temp != null) {
            System.out.println(temp.getData());
            temp = temp.getNext();
        }
    }

    public Node find(String data) {
        Node temp = this.head;

        // Search the node by data
        while (temp != null) {
            if (temp.getData().equals(data))
                return temp;
            temp = temp.getNext();
        }
        return null;
    }

Inserting Nodes at Specific Positions

    public void insert(String data, String dataBefore) {
        Node node = new Node(data);

        // If list is empty
        if (this.head == null) {
            this.head = this.tail = node;
        } else {
            // Find the node after which insertion happens
            Node nodeBefore = this.find(dataBefore);

            if (nodeBefore != null) {
                node.setNext(nodeBefore.getNext());
                nodeBefore.setNext(node);

                // If inserted after tail
                if (nodeBefore == this.tail)
                    this.tail = node;
            } else {
                System.out.println("Node not found");
            }
        }
    }

Deleting Nodes from the List

    public void delete(String data) {
        if (this.head == null) {
            System.out.println("List is empty");
            return;
        }

        // Find node to delete
        Node node = this.find(data);

        if (node == null) {
            System.out.println("Node not found");
        } else if (node == this.head) {
            // Deleting the head
            this.head = this.head.getNext();
            node.setNext(null);

            // If it was also the tail
            if (node == this.tail)
                this.tail = null;

        } else {
            Node nodeBefore = null;
            Node temp = this.head;

            // Traverse to find the previous node
            while (temp != null) {
                if (temp.getNext() == node) {
                    nodeBefore = temp;
                    break;
                }
                temp = temp.getNext();
            }

            // Remove the node
            nodeBefore.setNext(node.getNext());

            // If it was the tail
            if (node == this.tail)
                this.tail = nodeBefore;

            node.setNext(null);
        }
    }

Main Method and Execution

The following main method demonstrates the basic operations of the LinkedList.

    public static void main(String args[]) {
        LinkedList list = new LinkedList();

        list.addAtEnd("Milan");
        list.addAtEnd("Venice");
        list.addAtEnd("Munich");
        list.addAtEnd("Prague");
        list.addAtEnd("Vienna");

        list.display();

        System.out.println("--------------------------");

        list.delete("Venice");
        list.display();

        /*
        if(list.find("Munich") != null)
            System.out.println("Node found");
        else
            System.out.println("Node not found");
        */
    }
}