Java Data Structures: Implementing Linked Lists and BST Operations
Singly Linked List (SLL) Implementation in Java
Singly Linked List: Insertion Operations
This section demonstrates the basic structure and insertion methods for a Singly Linked List.
public class SinglyList {
private Node head;
private class Node {
int data;
Node next;
}
public boolean isEmpty() {
return (head == null);
}
public void insertFirst(int data) {
Node newNode = new Node();
newNode.data = data;
newNode.next = head;
head = newNode;
}
public void insertAfterData(int dataAfter, int item) {
if (isEmpty()) {
System.out.println("List is empty. Insertion not possible.");
return;
}
Node temp = head;
Node newNode = new Node();
newNode.data = item;
while (temp != null && temp.data != dataAfter) {
temp = temp.next;
}
if (temp == null) {
System.out.println("Node is not present in the list.");
return;
}
newNode.next = temp.next;
temp.next = newNode;
}
public void displayList() {
if (isEmpty()) {
System.out.println("List is empty");
return;
}
Node current = head;
while (current != null) {
System.out.print(current.data + " -> ");
current = current.next;
}
System.out.println("null");
}
}
Singly Linked List: Deletion Operations
This implementation includes a Node constructor and methods for deleting elements from the beginning, end, or after a specific data value.
public class SinglyList {
private Node head;
private class Node {
int data;
Node next;
Node(int data) {
this.data = data;
this.next = null;
}
}
public boolean isEmpty() {
return head == null;
}
public void insertFirst(int data) {
Node newNode = new Node(data);
newNode.next = head;
head = newNode;
}
public void insertLast(int data) {
Node newNode = new Node(data);
if (isEmpty()) {
head = newNode;
return;
}
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
}
public void insertAfterData(int dataAfter, int item) {
if (isEmpty()) {
System.out.println("List is empty. Insertion not possible.");
return;
}
Node temp = head;
while (temp != null && temp.data != dataAfter) {
temp = temp.next;
}
if (temp == null) {
System.out.println("Node with data " + dataAfter + " not found.");
return;
}
Node newNode = new Node(item);
newNode.next = temp.next;
temp.next = newNode;
}
public void deleteFirst() {
if (isEmpty()) {
System.out.println("List is empty. Deletion not possible.");
return;
}
head = head.next;
}
public void deleteLast() {
if (isEmpty()) {
System.out.println("List is empty. Deletion not possible.");
return;
}
if (head.next == null) {
head = null;
return;
}
Node temp = head;
while (temp.next.next != null) {
temp = temp.next;
}
temp.next = null;
}
public void deleteAfterData(int data) {
if (isEmpty()) {
System.out.println("List is empty. Deletion not possible.");
return;
}
Node temp = head;
while (temp != null && temp.data != data) {
temp = temp.next;
}
if (temp == null || temp.next == null) {
System.out.println("Node with data " + data + " not found or it's the last node.");
return;
}
temp.next = temp.next.next;
}
public void displayList() {
if (isEmpty()) {
System.out.println("List is empty.");
return;
}
Node temp = head;
while (temp != null) {
System.out.print(temp.data + " -> ");
temp = temp.next;
}
System.out.println("null");
}
}
Doubly Linked List (DLL) Implementation in Java
Doubly Linked List: Insertion Methods
The Doubly Linked List allows traversal in both forward and reverse directions, requiring prev and next pointers.
public class DoublyLinkedList {
private Node head;
private Node last;
private class Node {
int data;
Node next;
Node prev;
Node(int data) {
this.data = data;
}
}
public int listSize() {
Node trav = head;
int s = 0;
while (trav != null) {
s++;
trav = trav.next;
}
return s;
}
public void insertAtPosition(int data, int position) {
int size = listSize();
if (position > 0 && position <= size + 1) {
Node newNode = new Node(data);
if (position == 1) {
insertFirst(data);
} else if (position == size + 1) {
insertLast(data);
} else {
Node current = head;
// Traverse to the node *before* the insertion point (position - 1)
// Note: The original code traverses to the node *at* the insertion point
for (int j = 1; j < position; j++) {
current = current.next;
}
// current is now the node *at* the position where the new node should go
newNode.next = current;
newNode.prev = current.prev;
current.prev.next = newNode;
current.prev = newNode;
}
} else {
System.out.println("Position " + position + " not valid for list size " + size);
}
}
public boolean isEmpty() {
return (head == null);
}
public void displayList(Node trav) {
if (isEmpty()) {
System.out.println("List is empty. Nothing to show.");
return;
}
if (trav == null) {
trav = head;
}
System.out.println("Forward traversal");
while (trav != null) {
System.out.print(trav.data + " ");
last = trav; // Keep track of the last node
trav = trav.next;
}
System.out.println();
System.out.println("Reverse traversal");
while (last != null) {
System.out.print(last.data + " ");
last = last.prev;
}
System.out.println();
}
private void insertFirst(int data) {
Node newNode = new Node(data);
if (isEmpty()) {
head = last = newNode;
} else {
newNode.next = head;
head.prev = newNode;
head = newNode;
}
}
private void insertLast(int data) {
Node newNode = new Node(data);
if (isEmpty()) {
head = last = newNode;
} else {
last.next = newNode;
newNode.prev = last;
last = newNode;
}
}
}
Doubly Linked List: Deletion Methods
Methods for calculating size and deleting a node at a specific index (0-based).
// Assuming the class structure from the insertion section continues
public int listSize() {
Node trav = head;
int s = 0;
while (trav != null) {
s++;
trav = trav.next;
}
return s;
}
public void deleteAtPosition(int position) {
if (isEmpty()) {
System.out.println("List is empty (underflow). Deletion stopped.");
return;
}
int size = listSize();
// Assuming 0-based indexing for position
if (position < 0 || position >= size) {
System.out.println("Index " + position + " is not valid in the linked list of size " + size);
return;
}
Node current = head;
if (position == 0) {
deleteFirst();
} else if (position == size - 1) {
deleteLast();
} else {
// Traverse to the node to be deleted
for (int j = 0; j < position; j++) {
current = current.next;
}
// Bypass the current node
current.prev.next = current.next;
current.next.prev = current.prev;
}
}
// Note: deleteFirst and deleteLast methods must be implemented within the DLL class
public void displayList(Node trav) {
if (isEmpty()) {
System.out.println("List is empty. Nothing to show.");
return;
}
// The original code snippet had redundant initialization for 'next'
System.out.println("Forward traversal");
Node current = head;
while (current != null) {
System.out.print(current.data + " ");
current = current.next;
}
System.out.println();
System.out.println("Reverse traversal");
Node lastNode = head;
if (lastNode != null) {
while (lastNode.next != null) {
lastNode = lastNode.next;
}
while (lastNode != null) {
System.out.print(lastNode.data + " ");
lastNode = lastNode.prev;
}
}
System.out.println();
}
Binary Search Tree (BST) Operations
BST Insertion and Inorder Traversal
These recursive methods demonstrate how to insert a node into a Binary Search Tree and perform an inorder traversal (which outputs elements in sorted order).
// Assuming a Node class exists with data, left, and right fields
Node insertBinarySearchTree(Node root, int item) {
if (root == null) {
root = new Node(item);
return root;
}
if (item < root.data)
root.left = insertBinarySearchTree(root.left, item);
else
root.right = insertBinarySearchTree(root.right, item);
return root;
}
void inorderDisplay(Node root) {
if (root != null) {
inorderDisplay(root.left);
System.out.print(root.data + " ");
inorderDisplay(root.right);
}
}
