A Singly Linked List isĀ a specialized case of a generic linked list. In a singly linked list, each node links to only the next node in the sequence, i.e if we start traversing from the first node of the list, we can only move in one direction.
class Node<T>(var data: T, var next: Node<T>? = null)
The Node
class represents a node in the list, with a data
property to store the element and a next
property to reference the next node in the list.
class SinglyLinkedList<T> {
private var head: Node<T>? = null
private var tail: Node<T>? = null
The LinkedList
class represents the list itself, with a head
property to reference the first node, a tail
property to reference the last node, and a size
property to keep track of the number of nodes in the list. The class also provides methods to add and remove nodes from the list, check if the list is empty, and get the size of the list.
fun size(): Int {
var count = 0
var current = head
while (current != null) {
count++
current = current.next
}
size()
: Returns the number of nodes in the list.
fun addFirst(data: T) {
val newNode = Node(data)
if (isEmpty()) {
head = newNode
tail = newNode
} else {
newNode.next = head
head = newNode
}
}
The addFirst
method adds a node with the given element to the beginning of the list. If the list is empty, the new node becomes both the head and the tail of the list. Otherwise, the new node’s next
property is set to the current head, and the new node becomes the new head.
fun addLast(data: T) {
val newNode = Node(data)
if (isEmpty()) {
head = newNode
tail = newNode
} else {
tail?.next = newNode
tail = newNode
}
}
addLast(data: T)
: Adds a new node with the given data at the end of the list.
fun removeFirst(): T? {
if (isEmpty()) {
return null
}
val data = head?.data
if (head == tail) {
head = null
tail = null
} else {
head = head?.next
}
return data
}
removeFirst()
: Removes the first node from the list and returns its data.
fun removeLast(): T? {
if (isEmpty()) {
return null
}
val data = tail?.data
if (head == tail) {
head = null
tail = null
} else {
var current = head
while (current?.next != tail) {
current = current?.next
}
current?.next = null
tail = current
}
return data
}
removeLast()
: Removes the last node from the list and returns its data.
class Node<T>(var data: T, var next: Node<T>? = null)
class SinglyLinkedList<T> {
private var head: Node<T>? = null
private var tail: Node<T>? = null
fun isEmpty(): Boolean {
return head == null
}
fun size(): Int {
var count = 0
var current = head
while (current != null) {
count++
current = current.next
}
return count
}
fun addFirst(data: T) {
val newNode = Node(data)
if (isEmpty()) {
head = newNode
tail = newNode
} else {
newNode.next = head
head = newNode
}
}
fun addLast(data: T) {
val newNode = Node(data)
if (isEmpty()) {
head = newNode
tail = newNode
} else {
tail?.next = newNode
tail = newNode
}
}
fun removeFirst(): T? {
if (isEmpty()) {
return null
}
val data = head?.data
if (head == tail) {
head = null
tail = null
} else {
head = head?.next
}
return data
}
fun removeLast(): T? {
if (isEmpty()) {
return null
}
val data = tail?.data
if (head == tail) {
head = null
tail = null
} else {
var current = head
while (current?.next != tail) {
current = current?.next
}
current?.next = null
tail = current
}
return data
}
override fun toString(): String {
var current = head
var string = ""
while (current != null) {
string += "${current.data} -> "
current = current.next
}
string += "null"
return string
}
}
fun main() {
val list = SinglyLinkedList<Int>()
list.addFirst(1)
list.addLast(2)
list.addFirst(3)
println(list) // Output: 3 -> 1 -> 2 -> null
println("Size: ${list.size()}") // Output: Size: 3
println("Removed first element: ${list.removeFirst()}") // Output: Removed first element: 3
println(list) // Output: 1 -> 2 -> null
println("Removed last element: ${list.removeLast()}") // Output: Removed last element: 2
println(list) // Output: 1 -> null
}