I've written a basic implementation of a singly linked list in Scala. I would appreciate any feedback and improvements (especially the remove()
method, I feel like it could be implemented better).
Node class
class Node[T](data: T, var next: Option[Node[T]] = None) {
override def toString: String = data.toString
}
Singly linked list implementation:
class SinglyLinkedList[T](var head: Node[T], var size: Int = -1){
if(size == -1) size = calculateSize
private def calculateSize: Int = {
@scala.annotation.tailrec
def traverse(count: Int, curNode: Option[Node[T]]): Int = curNode match {
case None => count
case Some(node) => traverse(count + 1, node.next)
}
traverse(0, Some(head))
}
override def toString: String = {
@scala.annotation.tailrec
def traverse(sb: StringBuilder, curNode: Option[Node[T]]): String = curNode match {
case None => sb.append("None").toString
case Some(node) => traverse(sb append (node + " --> "), node.next)
}
traverse(new StringBuilder, Some(head))
}
def append(d: T): Unit = {
@scala.annotation.tailrec
def traverse(curNode: Option[Node[T]]): Unit = curNode.flatMap(_.next) match {
case None => curNode foreach (_.next = Some(new Node[T](d)))
case next => traverse(next)
}
traverse(Some(head))
size += 1
}
def remove(index: Int): Unit = {
@scala.annotation.tailrec
def traverse(elementsRemaining: Int, prevNode: Option[Node[T]], curNode: Option[Node[T]]): Unit = (elementsRemaining, curNode) match {
case (_, None) => throw new NoSuchElementException
case (0, n) =>
if(prevNode.isEmpty) head.next.foreach(head = _)
else prevNode.foreach(_.next = n.flatMap(_.next))
case (i, n) => traverse(i - 1, n, n.flatMap(_.next))
}
traverse(index, None, Some(head))
size -= 1
}
}