scala.collection.mutable.DoubleLinkedListLike.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-library Show documentation
Show all versions of scala-library Show documentation
Standard library for the Scala Programming Language
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
package scala.collection
package mutable
import scala.annotation.migration
/** This extensible class may be used as a basis for implementing double
* linked lists. Type variable `A` refers to the element type
* of the list, type variable `This` is used to model self
* types of linked lists.
*
* The invariant of this data structure is that `prev` is always a reference to
* the previous node in the list. If `this` is the first node of the list, `prev`
* will be `null`.
* Field `next` is set to `this` iff the list is empty.
*
* Examples (right arrow represents `next`, left arrow represents `prev`,
* `_` represents no value):
*
* {{{
*
* Empty:
*
* null <-- [ _ ] --,
* [ ] <-`
*
* Single element:
*
* null <-- [ x ] --> [ _ ] --,
* [ ] <-- [ ] <-`
*
* More elements:
*
* null <-- [ x ] --> [ y ] --> [ z ] --> [ _ ] --,
* [ ] <-- [ ] <-- [ ] <-- [ ] <-`
*
* }}}
*
* @author Matthias Zenger
* @version 1.0, 08/07/2003
* @since 2.8
*
* @tparam A type of the elements contained in the double linked list
* @tparam This the type of the actual linked list holding the elements
*
* @define Coll `DoubleLinkedList`
* @define coll double linked list
*/
trait DoubleLinkedListLike[A, This <: Seq[A] with DoubleLinkedListLike[A, This]] extends SeqLike[A, This] with LinkedListLike[A, This] { self =>
/** A reference to the node in the linked list preceeding the current node. */
var prev: This = _
// returns that list if this list is empty
// otherwise modifies this list
override def append(that: This): This =
if (isEmpty)
that
else {
if (next.isEmpty) {
next = that
if (that.nonEmpty) that.prev = repr
} else {
next.append(that)
}
repr
}
// cannot be called on empty lists
override def insert(that: This): Unit = {
super.insert(that)
if (that.nonEmpty) that.prev = repr
}
/** Removes the current node from the double linked list.
* If the node was chained into a double linked list, it will no longer
* be a part of it.
* If the node was the last node in the list, i.e. a sentinel, this method
* does nothing.
*
* '''Note:''' this method will not set the fields `elem`, `next` or `prev` of the
* current node, i.e. `this` node itself will still point "into" the list it
* was in.
*/
@migration("Double linked list now removes the current node from the list.", "2.9.0")
def remove(): Unit = if (nonEmpty) {
next.prev = prev
if (prev ne null) prev.next = next // because this could be the first node
}
private def atLocation[T](n: Int)(f: This => T)(onOutOfBounds: => T) = if (isEmpty) onOutOfBounds else {
var loc = repr
var left = n
while (left > 0) {
loc = loc.next
left -= 1
if (loc.isEmpty) onOutOfBounds
}
f(loc)
}
private def outofbounds(n: Int) = throw new IndexOutOfBoundsException(n.toString)
override def drop(n: Int): This = super[SeqLike].drop(n)
override def tail = drop(1)
override def apply(n: Int): A = atLocation(n)(_.elem)(outofbounds(n))
override def update(n: Int, x: A): Unit = atLocation(n)(_.elem = x)(outofbounds(n))
override def get(n: Int): Option[A] = atLocation[Option[A]](n)(x => Some(x.elem))(None)
}