Doubly-linked list/Element definition: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Wren}}: Minor tidy)
 
(11 intermediate revisions by 9 users not shown)
Line 11:
{{Template:See also lists}}
<br><br>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
 
TYPE ListNode=[
BYTE data
PTR prv,nxt]</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Doubly-linked_list_element_definition.png Screenshot from Atari 8-bit computer]
 
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">type Link;
type Link_Access is access Link;
type Link is record
Line 19 ⟶ 28:
Prev : Link_Access := null;
Data : Integer;
end record;</langsyntaxhighlight>
Using generics, the specification might look like this:
<langsyntaxhighlight lang="ada">generic
type Element_Type is private;
package Linked_List is
Line 43 ⟶ 52:
Traversing : Boolean := False; -- True when in a traversal.
end record;
end Linked_List;</langsyntaxhighlight>
In Ada 2005 this example can be written without declaration of an access type:
<langsyntaxhighlight lang="ada">type Link is limited record
Next : not null access Link := Link'Unchecked_Access;
Prev : not null access Link := Link'Unchecked_Access;
Data : Integer;
end record;</langsyntaxhighlight>
Here the list element is created already pointing to itself, so that no further initialization is required. The type of the element is marked as ''limited'' indicating that such elements have referential semantics and cannot be copied.
 
Line 58 ⟶ 67:
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-2.7 algol68g-2.7].}}
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d]}}
'''File: prelude/link.a68'''<langsyntaxhighlight lang="algol68"># -*- coding: utf-8 -*- #
CO REQUIRES:
MODE OBJVALUE = ~ # Mode/type of actual obj to be queued #
Line 72 ⟶ 81:
 
PROC obj link free = (REF OBJLINK free)VOID:
prev OF free := next OF free := obj queue empty # give the garbage collector a big hint #</langsyntaxhighlight>'''See also:''' [[Queue/Usage#ALGOL_68|Queue/Usage]]
 
=={{header|ALGOL W}}==
<langsyntaxhighlight lang="algolw"> % record type to hold an element of a doubly linked list of integers %
record DListIElement ( reference(DListIElement) prev
; integer iValue
; reference(DListIElement) next
);
% additional record types would be required for other element types %</langsyntaxhighlight>
 
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi}}
<syntaxhighlight lang="arm assembly">
<lang ARM Assembly>
 
/* ARM assembly Raspberry PI */
Line 97 ⟶ 106:
.struct NDlist_value + 4
NDlist_fin:
</syntaxhighlight>
</lang>
 
=={{header|AutoHotkey}}==
Line 103 ⟶ 112:
 
=={{header|Axe}}==
<langsyntaxhighlight lang="axe">Lbl LINK
r₂→{r₁}ʳ
0→{r₁+2}ʳ
Line 120 ⟶ 129:
Lbl VALUE
{r₁}ʳ
Return</langsyntaxhighlight>
 
=={{header|BBC BASIC}}==
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> DIM node{pPrev%, pNext%, iData%}
</syntaxhighlight>
</lang>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">link=(prev=) (next=) (data=)</langsyntaxhighlight>
 
=={{header|C}}==
It basically doesn't matter if we use the name link, node, Node or some other name. These are matters of taste and aesthetics. However, it is important that the C language is case-sensitive and that the namespace for structures is separate.
<langsyntaxhighlight lang="c">struct Node
{
struct Node *next;
struct Node *prev;
void *data;
};</langsyntaxhighlight>
An alternative technique is to define a pointer type by typedef as shown below. The advantage here is that you do not have to write struct everywhere - assuming that you will most often need a pointer to a struct Node, not the structure itself.
<syntaxhighlight lang="c">
<lang c>
struct Node;
typedef struct Node* Node;
Line 148 ⟶ 158:
void* data;
};
</syntaxhighlight>
</lang>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">class Link
{
public int Item { get; set; }
Line 163 ⟶ 173:
Next = next;
}
}</langsyntaxhighlight>
 
=={{header|C++}}==
C++ has doubly linked list class template in standard library. However actual list noded are treated as implementation detail and encapsulated inside list. If we were to reimplement list, then node could look like that:
<langsyntaxhighlight lang="cpp">template <typename T>
struct Node
{
Line 173 ⟶ 183:
Node* prev;
T data;
};</langsyntaxhighlight>
 
=={{header|Clojure}}==
Line 179 ⟶ 189:
This sort of mutable structure is not idiomatic in Clojure. [[../Definition#Clojure]] or a finger tree implementation would be better.
 
<langsyntaxhighlight Clojurelang="clojure">(defrecord Node [prev next data])
 
(defn new-node [prev next data]
(Node. (ref prev) (ref next) data))</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
 
<langsyntaxhighlight lang="lisp">(defstruct dlist head tail)
(defstruct dlink content prev next)</langsyntaxhighlight>
 
See the functions on the [[Doubly-Linked List]] page for the usage of these structures.
Line 193 ⟶ 203:
=={{header|D}}==
A default constructor is implicit:
<langsyntaxhighlight lang="d">struct Node(T) {
T data;
typeof(this)* prev, next;
Line 201 ⟶ 211:
alias N = Node!int;
N* n = new N(10);
}</langsyntaxhighlight>
 
=={{header|Delphi}}==
<langsyntaxhighlight lang="d">struct Node(T) {
 
type
Line 216 ⟶ 226:
end;
 
}</langsyntaxhighlight>
 
=={{header|E}}==
Line 222 ⟶ 232:
This does no type-checking, under the assumption that it is being used by a containing doubly-linked list object which enforces that invariant along with others such as that <code>element.getNext().getPrev() == element</code>. See [[Doubly-Linked List#E]] for an actual implementation (which uses slightly more elaborate nodes than this).
 
<langsyntaxhighlight lang="e">def makeElement(var value, var next, var prev) {
def element {
to setValue(v) { value := v }
Line 235 ⟶ 245:
return element
}</langsyntaxhighlight>
 
=={{header|Erlang}}==
Using the code in [[Doubly-linked_list/Definition]] the element is defined by:
<syntaxhighlight lang="erlang">
<lang Erlang>
new( Data ) -> erlang:spawn( fun() -> loop( Data, noprevious, nonext ) end ).
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
type 'a DLElm = {
mutable prev: 'a DLElm option
Line 250 ⟶ 260:
mutable next: 'a DLElm option
}
</syntaxhighlight>
</lang>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">TUPLE: node data next prev ;</langsyntaxhighlight>
 
=={{header|Fortran}}==
In ISO Fortran 95 or later:
<langsyntaxhighlight lang="fortran">type node
real :: data
type(node), pointer :: next => null(), previous => null()
Line 264 ⟶ 274:
! . . . .
!
type( node ), target :: head</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">type node
nxt as node ptr
prv as node ptr
dat as any ptr 'points to any kind of data; user's responsibility
'to keep track of what's actually in it
end type</langsyntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">type dlNode struct {
string
next, prev *dlNode
}</langsyntaxhighlight>
Or, using the [http://golang.org/pkg/container/list/#Element container/list] package:
<langsyntaxhighlight lang="go">import "container/list"
 
var node list.Element
// and using: node.Next(), node.Prev(), node.Value</langsyntaxhighlight>
 
=={{header|Haskell}}==
Line 290 ⟶ 300:
Note that unlike naive pointer manipulation which could corrupt the doubly-linked list, updateLeft and updateRight will always yield a well-formed data structure.
 
<langsyntaxhighlight lang="haskell">
data DList a = Leaf | Node (DList a) a (DList a)
 
Line 304 ⟶ 314:
where current = Node l v next
next = updateRight nr new
</syntaxhighlight>
</lang>
 
==Icon and {{header|Unicon}}==
Line 310 ⟶ 320:
Uses Unicon classes.
 
<syntaxhighlight lang="unicon">
<lang Unicon>
class DoubleLink (value, prev_link, next_link)
initially (value, prev_link, next_link)
Line 317 ⟶ 327:
self.next_link := next_link
end
</syntaxhighlight>
</lang>
 
=={{header|J}}==
Line 327 ⟶ 337:
Nevertheless, this is doable, though it necessarily departs from the definition specified at [[Doubly-linked_list/Definition#J]].
 
<langsyntaxhighlight lang="j">coclass'DoublyLinkedListElement'
create=:3 :0
this=:coname''
'predecessor successor data'=:y
successor__predecessor=: predecessor__successor=: this
)</langsyntaxhighlight>
 
Here, when we create a new list element, we need to specify its successor node and its predecessor node and the data to be stored in the node. To start a new list we will need a node that can be the head and the tail of the list -- this will be the successor node for the last element of the list and the predecessor node for the first element of the list:
 
<langsyntaxhighlight lang="j">coclass'DoublyLinkedListHead'
create=:3 :0
predecessor=:successor=:this=: coname''
)</langsyntaxhighlight>
 
=={{header|Java}}==
{{works with|Java|1.5+}}
<langsyntaxhighlight lang="java">public class Node<T> {
private T element;
private Node<T> next, prev;
Line 384 ⟶ 394:
return prev;
}
}</langsyntaxhighlight>
 
For use with [[Java]] 1.4 and below, delete all "<T>"s and replace T's with "Object".
Line 390 ⟶ 400:
=={{header|JavaScript}}==
Inherits from LinkedList (see [[Singly-Linked_List_(element)#JavaScript]])
<langsyntaxhighlight lang="javascript">function DoublyLinkedList(value, next, prev) {
this._value = value;
this._next = next;
Line 416 ⟶ 426:
}
 
var head = createDoublyLinkedListFromArray([10,20,30,40]);</langsyntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">abstract type AbstractNode{T} end
 
struct EmptyNode{T} <: AbstractNode{T} end
Line 428 ⟶ 438:
pred::AbstractNode{T}
succ::AbstractNode{T}
end</langsyntaxhighlight>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.2
 
class Node<T: Number>(var data: T, var prev: Node<T>? = null, var next: Node<T>? = null) {
Line 454 ⟶ 464:
println(n2)
println(n3)
}</langsyntaxhighlight>
 
{{out}}
Line 462 ⟶ 472:
3
</pre>
 
=={{header|Lang}}==
<syntaxhighlight lang="lang">
&Node = {
$next
$prev
$data
}
</syntaxhighlight>
 
=={{header|Lua}}==
see [[Doubly-linked_list/Definition#Lua]], essentially:
<langsyntaxhighlight lang="lua">local node = { data=data, prev=nil, next=nil }</langsyntaxhighlight>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Mathematica and the Wolfram Language have no lower-level way of handling pointers. It does have a built-in, compilable doubly-linked list data structure:
<langsyntaxhighlight Mathematicalang="mathematica">CreateDataStructure["DoublyLinkedList"]</langsyntaxhighlight>
 
=={{header|Modula-2}}==
 
<langsyntaxhighlight lang="modula2">TYPE
Link = POINTER TO LinkRcd;
LinkRcd = RECORD
Prev, Next: Link;
Data: INTEGER
END;</langsyntaxhighlight>
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">type
Node[T] = ref TNode[T]
 
TNode[T] = object
next, prev: Node[T]
data: T</langsyntaxhighlight>
 
=={{header|Oberon-2}}==
<langsyntaxhighlight lang="oberon2">
MODULE Box;
TYPE
Line 509 ⟶ 528:
(* ... *)
END Collections.
</syntaxhighlight>
</lang>
 
=={{header|Objeck}}==
<langsyntaxhighlight lang="objeck">class ListNode {
@value : Base;
@next : ListNode;
Line 544 ⟶ 563:
return @previous;
}
}</langsyntaxhighlight>
 
=={{header|OCaml}}==
===Imperative===
<langsyntaxhighlight lang="ocaml">type 'a dlink = {
mutable data: 'a;
mutable next: 'a dlink option;
Line 589 ⟶ 608:
in
aux
;;</langsyntaxhighlight>
 
<langsyntaxhighlight lang="ocaml"># let dl = dlink_of_list [1;2;3;4;5] in
iter_forward_dlink (Printf.printf "%d\n") dl ;;
1
Line 598 ⟶ 617:
4
5
- : unit = ()</langsyntaxhighlight>
 
===Functional===
Line 605 ⟶ 624:
examples of this page and its task, but in regular OCaml these kind of imperative structures can be advantageously replaced by a functional equivalent, that can be use in the same area, which is to have a list of elements and be able to point to one of these. We can use this type:
 
<langsyntaxhighlight lang="ocaml">type 'a nav_list = 'a list * 'a * 'a list</langsyntaxhighlight>
 
The middle element is the pointed item, and the two lists are the
previous and the following items.
Here are the associated functions:
<langsyntaxhighlight lang="ocaml">let nav_list_of_list = function
| hd::tl -> [], hd, tl
| [] -> invalid_arg "empty list"
Line 627 ⟶ 646:
prev_tl, prev, item::next
| _ ->
failwith "begin of nav_list reached"</langsyntaxhighlight>
<langsyntaxhighlight lang="ocaml"># let nl = nav_list_of_list [1;2;3;4;5] ;;
val nl : 'a list * int * int list = ([], 1, [2; 3; 4; 5])
# let nl = next nl ;;
Line 636 ⟶ 655:
 
# current nl ;;
- : int = 3</langsyntaxhighlight>
 
=={{header|Oforth}}==
Line 642 ⟶ 661:
Complete definition is here : [[../Definition#Oforth]]
 
<langsyntaxhighlight lang="oforth">Object Class new: DNode(value, mutable prev, mutable next)</langsyntaxhighlight>
 
=={{header|Oz}}==
We show how to create a new node as a record value.
<langsyntaxhighlight lang="oz">fun {CreateNewNode Value}
node(prev:{NewCell _}
next:{NewCell _}
value:Value)
end</langsyntaxhighlight>
Note: this is for illustrative purposes only. In a real Oz program, you would use one of the existing data types.
 
=={{header|Pascal}}==
 
<langsyntaxhighlight lang="pascal">type link_ptr = ^link;
data_ptr = ^data; (* presumes that type 'data' is defined above *)
link = record
Line 661 ⟶ 680:
next: link_ptr;
data: data_ptr;
end;</langsyntaxhighlight>
 
=={{header|Perl}}==
 
<langsyntaxhighlight lang="perl">my %node = (
data => 'say what',
next => \%foo_node,
prev => \%bar_node,
);
$node{next} = \%quux_node; # mutable</langsyntaxhighlight>
 
=={{header|Phix}}==
In Phix, types are used for validation and debugging rather than specification purposes. For extensive run-time checking you could use
<!--<langsyntaxhighlight Phixlang="phix">(notonline)-->
<span style="color: #008080;">enum</span> <span style="color: #000000;">NEXT</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PREV</span><span style="color: #0000FF;">,</span><span style="color: #000000;">DATA</span>
<span style="color: #008080;">type</span> <span style="color: #000000;">slnode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">DATA</span> <span style="color: #008080;">and</span> <span style="color: #0000FF;"><</span><span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">udt</span><span style="color: #0000FF;"></</span><span style="color: #000000;">i</span><span style="color: #0000FF;">>(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DATA</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">NEXT</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">and</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">PREV</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<!--</langsyntaxhighlight>-->
But more often you would just use the builtin sequences. See also [[Singly-linked_list/Element_definition#Phix|Singly-linked_list/Element_definition]].
 
Memory is automatically reclaimed the moment items are no longer needed.
 
Note that automatic typechecking does not occur under pwa/p2js, that is desktop/Phix only (for the debugging stage) but you can invoke a type such as the above explicitly.
 
=={{header|PicoLisp}}==
Line 697 ⟶ 718:
With that, 'cddr' can be used to access the next, and 'cadr' to access the
previous element.
<langsyntaxhighlight PicoLisplang="picolisp">(de 2tail (X DLst)
(let L (cdr DLst)
(con DLst (cons X L NIL))
Line 712 ⟶ 733:
 
# We prepend 'not' to the list in the previous example
(2head 'not *DLst)</langsyntaxhighlight>
For output of the example data, see [[Doubly-linked list/Traversal#PicoLisp]].
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
define structure
1 Node,
Line 731 ⟶ 752:
...
P = P => back_pointer; /* P now points at the previous node. */
</syntaxhighlight>
</lang>
 
=={{header|Plain English}}==
When you define a <code>thing</code>, you are defining a record as a doubly-linked list element. <code>next</code> and <code>previous</code> fields are implicitly added to the record that can be used to build and traverse a list.
<langsyntaxhighlight lang="plainenglish">An element is a thing with a number.</langsyntaxhighlight>
 
=={{header|Pop11}}==
 
<langsyntaxhighlight lang="pop11">uses objectclass;
define :class Link;
slot next = [];
slot prev = [];
slot data = [];
enddefine;</langsyntaxhighlight>
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Structure node
*prev.node
*next.node
value.i
EndStructure</langsyntaxhighlight>
 
=={{header|Python}}==
 
<langsyntaxhighlight lang="python">class Node(object):
def __init__(self, data = None, prev = None, next = None):
self.prev = prev
Line 773 ⟶ 794:
while c != None:
yield c
c = c.prev</langsyntaxhighlight>
 
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">
(define-struct dlist (head tail) #:mutable)
(define-struct dlink (content prev next) #:mutable)
</syntaxhighlight>
</lang>
 
See the functions on the [[Doubly-Linked List]] page for the usage of these structures.
Line 787 ⟶ 808:
(formerly Perl 6)
 
<syntaxhighlight lang="raku" perl6line>role DLElem[::T] {
has DLElem[T] $.prev is rw;
has DLElem[T] $.next is rw;
Line 817 ⟶ 838:
$!prev.next = $!next; # conveniently returns next element
}
}</langsyntaxhighlight>
 
=={{header|REXX}}==
Line 844 ⟶ 865:
║ @del k,m ─── deletes the M items starting with item K. ║
╚═════════════════════════════════════════════════════════════════════════╝
<langsyntaxhighlight lang="rexx">/*REXX program implements various List Manager functions (see the documentation above).*/
call sy 'initializing the list.' ; call @init
call sy 'building list: Was it a cat I saw' ; call @put "Was it a cat I saw"
Line 887 ⟶ 908:
/*──────────────────────────────────────────────────────────────────────────────────────*/
@show: procedure expose $.; parse arg k,m,dir; if dir==-1 & k=='' then k=$.#
m=p(m $.#); call @parms 'kmd'; say @get(k,m, dir); return</langsyntaxhighlight>
'''output'''
<pre>
Line 927 ⟶ 948:
=={{header|Ruby}}==
Extending [[Singly-Linked List (element)#Ruby]]
<langsyntaxhighlight lang="ruby">class DListNode < ListNode
attr_accessor :prev
# accessors :succ and :value are inherited
Line 946 ⟶ 967:
end
 
list = DListNode.from_values 1,2,3,4</langsyntaxhighlight>
 
=={{header|Rust}}==
Line 952 ⟶ 973:
 
=== Simply using the standard library ===
<langsyntaxhighlight lang="rust">use std::collections::LinkedList;
fn main() {
// Doubly linked list containing 32-bit integers
let list = LinkedList::<i32>::new();
}</langsyntaxhighlight>
 
=== The behind-the-scenes implementation ===
Line 963 ⟶ 984:
The standard library uses the (currently) unstable `Shared<T>` type which indicates that the ownership of its contained type has shared ownership. It is guaranteed not to be null, is variant over <code>T</code> (meaning that an <code>&Shared<&'static T></code> may be used where a <code>&Shared<&'a T></code> is expected, indicates to the compiler that it may own a <code>T</code>) and may be dereferenced to a mutable pointer (<code>*mut T</code>). All of the above may be accomplished in standard stable Rust, except for the non-null guarantee which allows the compiler to make a few extra optimizations.
 
<langsyntaxhighlight lang="rust">pub struct LinkedList<T> {
head: Option<Shared<Node<T>>>,
tail: Option<Shared<Node<T>>>,
Line 974 ⟶ 995:
prev: Option<Shared<Node<T>>>,
element: T,
}</langsyntaxhighlight>
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">var node = Hash.new(
data => 'say what',
next => foo_node,
Line 983 ⟶ 1,004:
);
 
node{:next} = quux_node; # mutable</langsyntaxhighlight>
 
=={{header|Swift}}==
 
<syntaxhighlight lang="swift">typealias NodePtr<T> = UnsafeMutablePointer<Node<T>>
 
class Node<T> {
var value: T
fileprivate var prev: NodePtr<T>?
fileprivate var next: NodePtr<T>?
 
init(value: T, prev: NodePtr<T>? = nil, next: NodePtr<T>? = nil) {
self.value = value
self.prev = prev
self.next = next
}
}
</syntaxhighlight>
 
=={{header|Tcl}}==
{{eff note|Tcl|list}}
{{works with|Tcl|8.6}} or {{libheader|TclOO}}
<langsyntaxhighlight lang="tcl">oo::class create List {
variable content next prev
constructor {value {list ""}} {
Line 1,007 ⟶ 1,045:
set prev {*}$args
}
}</langsyntaxhighlight>
 
=={{header|Visual Basic .NET}}==
 
<langsyntaxhighlight lang="vbnet">Public Class Node(Of T)
Public Value As T
Public [Next] As Node(Of T)
Public Previous As Node(Of T)
End Class</langsyntaxhighlight>
 
=={{header|Wren}}==
{{libheader|Wren-llist}}
The DNode class in the above module is the element type for the DLinkedList class which is a generic doubly-linked list. The latter is implemented in such a way that the user does not need to deal directly with DNode though for the purposes of the task we show below how instances of it can be created and manipulated.
<langsyntaxhighlight ecmascriptlang="wren">import "./llist" for DNode
 
var dn1 = DNode.new(1)
Line 1,029 ⟶ 1,067:
dn2.next = null
System.print(["node 1", "data = %(dn1.data)", "prev = %(dn1.prev)", "next = %(dn1.next)"])
System.print(["node 2", "data = %(dn2.data)", "prev = %(dn2.prev)", "next = %(dn2.next)"])</langsyntaxhighlight>
 
{{out}}
Line 1,036 ⟶ 1,074:
[node 2, data = 2, prev = 1, next = null]
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">
def \Node\ Prev, Data, Next; \Element (Node) definition
</syntaxhighlight>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">class Node{
fcn init(_value,_prev=Void,_next=Void)
{ var value=_value, prev=_prev, next=_next; }
fcn toString{ value.toString() }
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">a,b:=Node(1),Node("three");
a.next=b; b.prev=a;
println(a.next," ",b.prev);</langsyntaxhighlight>
{{out}}
<pre>

Latest revision as of 11:59, 28 November 2023

Task
Doubly-linked list/Element definition
You are encouraged to solve this task according to the task description, using any language you may know.
Task

Define the data structure for a doubly-linked list element.

The element should include a data member to hold its value and pointers to both the next element in the list and the previous element in the list.

The pointers should be mutable.


See also



Action!

DEFINE PTR="CARD"

TYPE ListNode=[
  BYTE data
  PTR prv,nxt]
Output:

Screenshot from Atari 8-bit computer

Ada

type Link;
type Link_Access is access Link;
type Link is record
  Next : Link_Access := null;
  Prev : Link_Access := null;
  Data : Integer;
end record;

Using generics, the specification might look like this:

generic
   type Element_Type is private;
package Linked_List is
   type List_Type is limited private;
...
private
   type List_Element;
   type List_Element_Ptr is access list_element;
   type List_Element is
      record
	 Prev : List_Element_Ptr;
	 Data : Element_Type;
	 Next : List_Element_Ptr;
      end record;
   type List_Type is
      record
	 Head        : List_Element_Ptr;     -- Pointer to first element.
	 Tail        : List_Element_Ptr;     -- Pointer to last element.
	 Cursor      : List_Element_Ptr;     -- Pointer to cursor element.
	 Count       : Natural := 0;         -- Number of items in list.
	 Traversing  : Boolean := False;     -- True when in a traversal.
      end record;
end Linked_List;

In Ada 2005 this example can be written without declaration of an access type:

type Link is limited record
   Next : not null access Link := Link'Unchecked_Access;
   Prev : not null access Link := Link'Unchecked_Access;
   Data : Integer;
end record;

Here the list element is created already pointing to itself, so that no further initialization is required. The type of the element is marked as limited indicating that such elements have referential semantics and cannot be copied.

Ada's standard container library includes a generic doubly linked list. The structure of the link element is private.

ALGOL 68

Works with: ALGOL 68 version Revision 1.
Works with: ALGOL 68G version Any - tested with release algol68g-2.7.
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d

File: prelude/link.a68

# -*- coding: utf-8 -*- #
CO REQUIRES:
  MODE OBJVALUE = ~ # Mode/type of actual obj to be queued #
END CO

MODE OBJLINK = STRUCT(
  REF OBJLINK next,
  REF OBJLINK prev,
  OBJVALUE value # ... etc. required #
);

PROC obj link new = REF OBJLINK: HEAP OBJLINK;

PROC obj link free = (REF OBJLINK free)VOID:
   prev OF free := next OF free := obj queue empty # give the garbage collector a big hint #

See also: Queue/Usage

ALGOL W

    % record type to hold an element of a doubly linked list of integers      %
    record DListIElement ( reference(DListIElement) prev
                         ; integer iValue
                         ; reference(DListIElement) next
                         );
    % additional record types would be required for other element types       %

ARM Assembly

Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */

/* structure Node Doublylinked List*/
    .struct  0
NDlist_next:                    @ next element
    .struct  NDlist_next + 4 
NDlist_prev:                    @ previous element
    .struct  NDlist_prev + 4 
NDlist_value:                   @ element value or key
    .struct  NDlist_value + 4 
NDlist_fin:

AutoHotkey

see Doubly-linked list/AutoHotkey

Axe

Lbl LINK
r₂→{r₁}ʳ
0→{r₁+2}ʳ
0→{r₁+4}ʳ
r₁
Return

Lbl NEXT
{r₁+2}ʳ
Return

Lbl PREV
{r₁+4}ʳ
Return

Lbl VALUE
{r₁}ʳ
Return

BASIC

BBC BASIC

      DIM node{pPrev%, pNext%, iData%}

Bracmat

link=(prev=) (next=) (data=)

C

It basically doesn't matter if we use the name link, node, Node or some other name. These are matters of taste and aesthetics. However, it is important that the C language is case-sensitive and that the namespace for structures is separate.

struct Node 
{
  struct Node *next;
  struct Node *prev;
  void  *data;
};

An alternative technique is to define a pointer type by typedef as shown below. The advantage here is that you do not have to write struct everywhere - assuming that you will most often need a pointer to a struct Node, not the structure itself.

struct Node;
typedef struct Node* Node;
struct Node
{
  Node next;
  Node prev;
  void* data;
};

C#

class Link
{
    public int Item { get; set; }
    public Link Prev { get; set; }
    public Link Next { get; set; }

    //A constructor is not neccessary, but could be useful
    public Link(int item, Link prev = null, Link next = null) {
        Item = item;
        Prev = prev;
        Next = next;
    }
}

C++

C++ has doubly linked list class template in standard library. However actual list noded are treated as implementation detail and encapsulated inside list. If we were to reimplement list, then node could look like that:

template <typename T>
struct Node
{
    Node* next;
    Node* prev;
    T data;
};

Clojure

This sort of mutable structure is not idiomatic in Clojure. Doubly-linked list/Definition#Clojure or a finger tree implementation would be better.

(defrecord Node [prev next data])

(defn new-node [prev next data]
  (Node. (ref prev) (ref next) data))

Common Lisp

(defstruct dlist head tail)
(defstruct dlink content prev next)

See the functions on the Doubly-Linked List page for the usage of these structures.

D

A default constructor is implicit:

struct Node(T) {
    T data;
    typeof(this)* prev, next;
}

void main() {
    alias N = Node!int;
    N* n = new N(10);
}

Delphi

struct Node(T) {

type

    pList = ^List ;

    list = record
       data : pointer ;
       prev : pList ;
       next : pList ;
    end;

}

E

This does no type-checking, under the assumption that it is being used by a containing doubly-linked list object which enforces that invariant along with others such as that element.getNext().getPrev() == element. See Doubly-Linked List#E for an actual implementation (which uses slightly more elaborate nodes than this).

def makeElement(var value, var next, var prev) {
    def element {
        to setValue(v) { value := v }
        to getValue() { return value }

        to setNext(n) { next := n }
        to getNext() { return next }

        to setPrev(p) { prev := p }
        to getPrev() { return prev }     
    }
   
    return element
}

Erlang

Using the code in Doubly-linked_list/Definition the element is defined by:

new( Data ) -> erlang:spawn( fun() -> loop( Data, noprevious, nonext ) end ).

F#

type 'a DLElm = {
    mutable prev: 'a DLElm option
    data: 'a
    mutable next: 'a DLElm option
}

Factor

TUPLE: node data next prev ;

Fortran

In ISO Fortran 95 or later:

type node
   real :: data
   type(node), pointer :: next => null(), previous => null()
end type node
!
! . . . .
!
type( node ), target :: head

FreeBASIC

type node
    nxt as node ptr
    prv as node ptr
    dat as any ptr   'points to any kind of data; user's responsibility
                     'to keep track of what's actually in it
end type

Go

type dlNode struct {
    string
    next, prev *dlNode
}

Or, using the container/list package:

import "container/list"

var node list.Element
// and using: node.Next(), node.Prev(), node.Value

Haskell

Haskell in general doesn't have mutability so the following 'mutator' functions use lazy evaluation instead.

Note that unlike naive pointer manipulation which could corrupt the doubly-linked list, updateLeft and updateRight will always yield a well-formed data structure.

data DList a = Leaf | Node (DList a) a (DList a)

updateLeft _ Leaf = Leaf
updateLeft Leaf (Node _ v r) = Node Leaf v r
updateLeft new@(Node nl _ _) (Node _ v r) = current
    where current = Node prev v r
          prev = updateLeft nl new

updateRight _ Leaf = Leaf
updateRight Leaf (Node l v _) = Node l v Leaf  
updateRight new@(Node _ _ nr) (Node l v _) = current
    where current = Node l v next
          next = updateRight nr new

Icon and Unicon

Uses Unicon classes.

class DoubleLink (value, prev_link, next_link)
  initially (value, prev_link, next_link)
    self.value := value
    self.prev_link := prev_link    # links are 'null' if not given
    self.next_link := next_link
end

J

As discussed in Doubly-linked_list/Definition#J, doubly linked lists are antithetical to J's design. Defining individual elements as independent structures is even worse. Now each element of the list must contain three arrays (everything in J is an array), all so that we can implement a list.

Yo Dawg, we heard you like lists, so we put lists in your lists so you can list while you list.

Nevertheless, this is doable, though it necessarily departs from the definition specified at Doubly-linked_list/Definition#J.

coclass'DoublyLinkedListElement'
create=:3 :0
  this=:coname''
  'predecessor successor data'=:y
  successor__predecessor=: predecessor__successor=: this
)

Here, when we create a new list element, we need to specify its successor node and its predecessor node and the data to be stored in the node. To start a new list we will need a node that can be the head and the tail of the list -- this will be the successor node for the last element of the list and the predecessor node for the first element of the list:

coclass'DoublyLinkedListHead'
create=:3 :0
  predecessor=:successor=:this=: coname''
)

Java

Works with: Java version 1.5+
public class Node<T> {
   private T element;
   private Node<T> next, prev;

   public Node<T>(){
      next = prev = element = null;
   }

   public Node<T>(Node<T> n, Node<T> p, T elem){
      next = n;
      prev = p;
      element = elem;
   }

   public void setNext(Node<T> n){
      next = n;
   }

   public Node<T> getNext(){
      return next;
   }

   public void setElem(T elem){
      element = elem;
   }

   public T getElem(){
      return element;
   }

   public void setNext(Node<T> n){
      next = n;
   }

   public Node<T> setPrev(Node<T> p){
      prev = p;
   }

   public getPrev(){
      return prev;
   }
}

For use with Java 1.4 and below, delete all "<T>"s and replace T's with "Object".

JavaScript

Inherits from LinkedList (see Singly-Linked_List_(element)#JavaScript)

function DoublyLinkedList(value, next, prev) {
    this._value = value;
    this._next = next;
    this._prev = prev;
}
// from LinkedList, inherit: value(), next(), traverse(), print()
DoublyLinkedList.prototype = new LinkedList();

DoublyLinkedList.prototype.prev = function() {
    if (arguments.length == 1) 
        this._prev = arguments[0];
    else
        return this._prev;
}

function createDoublyLinkedListFromArray(ary) {
    var node, prev, head = new DoublyLinkedList(ary[0], null, null);
    prev = head;
    for (var i = 1; i < ary.length; i++) {
        node = new DoublyLinkedList(ary[i], null, prev);
        prev.next(node);
        prev = node;
    }
    return head;
}

var head = createDoublyLinkedListFromArray([10,20,30,40]);

Julia

Works with: Julia version 0.6
abstract type AbstractNode{T} end

struct EmptyNode{T} <: AbstractNode{T} end
mutable struct Node{T} <: AbstractNode{T}
    value::T
    pred::AbstractNode{T}
    succ::AbstractNode{T}
end

Kotlin

// version 1.1.2

class Node<T: Number>(var data: T, var prev: Node<T>? = null, var next: Node<T>? = null) {
    override fun toString(): String {
        val sb = StringBuilder(this.data.toString())
        var node = this.next
        while (node != null) {
            sb.append(" -> ", node.data.toString())
            node = node.next
        }
        return sb.toString()
    }
}

fun main(args: Array<String>) {
    val n1 = Node(1)
    val n2 = Node(2, n1)
    n1.next = n2
    val n3 = Node(3, n2)
    n2.next = n3
    println(n1)
    println(n2)
    println(n3)
}
Output:
1 -> 2 -> 3
2 -> 3
3

Lang

&Node = {
	$next
	$prev
	$data
}

Lua

see Doubly-linked_list/Definition#Lua, essentially:

local node = { data=data, prev=nil, next=nil }

Mathematica/Wolfram Language

Mathematica and the Wolfram Language have no lower-level way of handling pointers. It does have a built-in, compilable doubly-linked list data structure:

CreateDataStructure["DoublyLinkedList"]

Modula-2

TYPE
  Link = POINTER TO LinkRcd;
  LinkRcd = RECORD
    Prev, Next: Link;
    Data: INTEGER
  END;

Nim

type
  Node[T] = ref TNode[T]

  TNode[T] = object
    next, prev: Node[T]
    data: T

Oberon-2

MODULE Box;
TYPE
        Object* = POINTER TO ObjectDesc;
	ObjectDesc* = (* ABSTRACT *) RECORD
	END;

        (* ... *)
END Box.

MODULE Collections;
TYPE
	Node* = POINTER TO NodeDesc;
	NodeDesc* = (* ABSTRACT *) RECORD
		prev-,next-: Node;
                value-: Box.Object;
	END;

        (* ... *)
END Collections.

Objeck

class ListNode {
  @value : Base;
  @next : ListNode;
  @previous: ListNode;

  New(value : Base) {
    @value := value;
  }
  
  method : public : Set(value : Base) ~ Nil {
    @value := value;
  }

  method : public : Get() ~ Base {
    return @value;
  }

  method : public : SetNext(next :  Collection.ListNode) ~ Nil {
    @next := next;
  }

  method : public : GetNext() ~ ListNode {
    return @next;
  }

  method : public : SetPrevious(previous :  Collection.ListNode) ~ Nil {
    @previous := previous;
  }

  method : public : GetPrevious() ~ ListNode {
    return @previous;
  }
}

OCaml

Imperative

type 'a dlink = {
  mutable data: 'a;
  mutable next: 'a dlink option;
  mutable prev: 'a dlink option;
}

let dlink_of_list li =
  let f prev_dlink x =
    let dlink = {
      data = x;
      prev = None;
      next = prev_dlink }
    in
    begin match prev_dlink with
    | None -> ()
    | Some prev_dlink ->
        prev_dlink.prev <- Some dlink
    end;
    Some dlink
  in
  List.fold_left f None (List.rev li)
;;

let list_of_dlink =
  let rec aux acc = function
  | None -> List.rev acc
  | Some{ data = d;
          prev = _;
          next = next } -> aux (d::acc) next
  in
  aux []
;;

let iter_forward_dlink f =
  let rec aux = function
  | None -> ()
  | Some{ data = d;
          prev = _;
          next = next } -> f d; aux next
  in
  aux
;;
# let dl = dlink_of_list [1;2;3;4;5] in
  iter_forward_dlink (Printf.printf "%d\n") dl ;;
1
2
3
4
5
- : unit = ()

Functional

The previous implementation is the strict equivalent of the other examples of this page and its task, but in regular OCaml these kind of imperative structures can be advantageously replaced by a functional equivalent, that can be use in the same area, which is to have a list of elements and be able to point to one of these. We can use this type:

type 'a nav_list = 'a list * 'a * 'a list

The middle element is the pointed item, and the two lists are the previous and the following items. Here are the associated functions:

let nav_list_of_list = function
  | hd::tl -> [], hd, tl
  | [] -> invalid_arg "empty list"

let current = function
  | _, item, _ -> item

let next = function
  | prev, item, next::next_tl ->
      item::prev, next, next_tl
  | _ ->
      failwith "end of nav_list reached"

let prev = function
  | prev::prev_tl, item, next ->
      prev_tl, prev, item::next
  | _ ->
      failwith "begin of nav_list reached"
# let nl = nav_list_of_list [1;2;3;4;5] ;;
val nl : 'a list * int * int list = ([], 1, [2; 3; 4; 5])
# let nl = next nl ;;
val nl : int list * int * int list = ([1], 2, [3; 4; 5])
# let nl = next nl ;;
val nl : int list * int * int list = ([2; 1], 3, [4; 5])

# current nl ;;
- : int = 3

Oforth

Complete definition is here : Doubly-linked list/Definition#Oforth

Object Class new: DNode(value, mutable prev, mutable next)

Oz

We show how to create a new node as a record value.

fun {CreateNewNode Value}
   node(prev:{NewCell _}
	next:{NewCell _}
	value:Value)
end

Note: this is for illustrative purposes only. In a real Oz program, you would use one of the existing data types.

Pascal

type link_ptr = ^link;
     data_ptr = ^data; (* presumes that type 'data' is defined above *)
     link = record
              prev: link_ptr;
              next: link_ptr;
              data: data_ptr;
            end;

Perl

my %node = (
     data => 'say what',
     next => \%foo_node,
     prev => \%bar_node,
);
$node{next} = \%quux_node;  # mutable

Phix

In Phix, types are used for validation and debugging rather than specification purposes. For extensive run-time checking you could use

enum NEXT,PREV,DATA
type slnode(object x)
    return (sequence(x) and length(x)=DATA and <i>udt</i>(x[DATA]) and integer(x[NEXT] and integer(x[PREV]))
end type

But more often you would just use the builtin sequences. See also Singly-linked_list/Element_definition.

Memory is automatically reclaimed the moment items are no longer needed.

Note that automatic typechecking does not occur under pwa/p2js, that is desktop/Phix only (for the debugging stage) but you can invoke a type such as the above explicitly.

PicoLisp

We use (in addition to the header structure described in Doubly-linked list/Definition#PicoLisp) two cells per doubly-linked list element:

        +-----+-----+     +-----+-----+
        | Val |  ---+---> |  |  |  ---+---> next
        +-----+-----+     +--+--+-----+
                             |
                    prev <---+

With that, 'cddr' can be used to access the next, and 'cadr' to access the previous element.

(de 2tail (X DLst)
   (let L (cdr DLst)
      (con DLst (cons X L NIL))
      (if L
         (con (cdr L) (cdr DLst))
         (set DLst (cdr DLst)) ) ) )

(de 2head (X DLst)
   (let L (car DLst)                  # Get current data list
      (set DLst (cons X NIL L))       # Prepend two new cons pairs
      (if L                           # Unless DLst was empty
         (set (cdr L) (car DLst))     # set new 'prev' link
         (con DLst (car DLst)) ) ) )  # otherwise set 'end' link

# We prepend 'not' to the list in the previous example
(2head 'not *DLst)

For output of the example data, see Doubly-linked list/Traversal#PicoLisp.

PL/I

define structure
   1 Node,
      2 value        fixed decimal,
      2 back_pointer handle(Node),
      2 fwd_pointer  handle(Node);

P = NEW(: Node :); /* Creates a node, and lets P point at it.       */
get (P => value);  /* Reads in a value to the node we just created. */

/* Assuming that back_pointer and fwd_pointer point at other nodes, */
/* we can say ...                                                   */
P = P => fwd_pointer; /* P now points at the next node.             */
...
P = P => back_pointer; /* P now points at the previous node.        */

Plain English

When you define a thing, you are defining a record as a doubly-linked list element. next and previous fields are implicitly added to the record that can be used to build and traverse a list.

An element is a thing with a number.

Pop11

uses objectclass;
define :class Link;
    slot next = [];
    slot prev = [];
    slot data = [];
enddefine;

PureBasic

Structure node
  *prev.node
  *next.node
  value.i 
EndStructure

Python

class Node(object):
     def __init__(self, data = None, prev = None, next = None):
         self.prev = prev
         self.next = next
         self.data = data
     def __str__(self):
         return str(self.data)
     def __repr__(self):
         return repr(self.data)
     def iter_forward(self):
         c = self
         while c != None:
             yield c
             c = c.next
     def iter_backward(self):
         c = self
         while c != None:
             yield c
             c = c.prev

Racket

(define-struct dlist (head tail) #:mutable)
(define-struct dlink (content prev next) #:mutable)

See the functions on the Doubly-Linked List page for the usage of these structures.

Raku

(formerly Perl 6)

role DLElem[::T] {
    has DLElem[T] $.prev is rw;
    has DLElem[T] $.next is rw;
    has T $.payload = T;

    method pre-insert(T $payload) {
        die "Can't insert before beginning" unless $!prev;
        my $elem = ::?CLASS.new(:$payload);
        $!prev.next = $elem;
        $elem.prev = $!prev;
        $elem.next = self;
        $!prev = $elem;
        $elem;
    }

    method post-insert(T $payload) {
        die "Can't insert after end" unless $!next;
        my $elem = ::?CLASS.new(:$payload);
        $!next.prev = $elem;
        $elem.next = $!next;
        $elem.prev = self;
        $!next = $elem;
        $elem;
    }

    method delete {
        die "Can't delete a sentinel" unless $!prev and $!next;
        $!next.prev = $!prev;
        $!prev.next = $!next;   # conveniently returns next element
    }
}

REXX

REXX doesn't have linked lists, as there are no pointers (or handles).
However, linked lists can be simulated with lists in REXX.

       ╔═════════════════════════════════════════════════════════════════════════╗
       ║        ☼☼☼☼☼☼☼☼☼☼☼ Functions of the  List Manager ☼☼☼☼☼☼☼☼☼☼☼           ║
       ║   @init      ─── initializes the List.                                  ║
       ║                                                                         ║
       ║   @size      ─── returns the size of the List  [could be a  0  (zero)]. ║
       ║                                                                         ║
       ║   @show      ─── shows (displays) the complete List.                    ║
       ║   @show k,1  ─── shows (displays) the  Kth  item.                       ║
       ║   @show k,m  ─── shows (displays)  M  items,  starting with  Kth  item. ║
       ║   @show ,,─1 ─── shows (displays) the complete List backwards.          ║
       ║                                                                         ║
       ║   @get  k    ─── returns the  Kth  item.                                ║
       ║   @get  k,m  ─── returns the  M  items  starting with the  Kth  item.   ║
       ║                                                                         ║
       ║   @put  x    ─── adds the  X  items to the  end  (tail) of the List.    ║
       ║   @put  x,0  ─── adds the  X  items to the start (head) of the List.    ║
       ║   @put  x,k  ─── adds the  X  items to before of the  Kth  item.        ║
       ║                                                                         ║
       ║   @del  k    ─── deletes the item  K.                                   ║
       ║   @del  k,m  ─── deletes the   M  items  starting with item  K.         ║
       ╚═════════════════════════════════════════════════════════════════════════╝
/*REXX program implements various List Manager functions  (see the documentation above).*/
call sy 'initializing the list.'            ;  call @init
call sy 'building list: Was it a cat I saw' ;  call @put "Was it a cat I saw"
call sy 'displaying list size.'             ;  say  "list size="@size()
call sy 'forward list'                      ;  call @show
call sy 'backward list'                     ;  call @show ,,-1
call sy 'showing 4th item'                  ;  call @show 4,1
call sy 'showing 5th & 6th items'           ;  call @show 5,2
call sy 'adding item before item 4: black'  ;  call @put "black",4
call sy 'showing list'                      ;  call @show
call sy 'adding to tail: there, in the ...' ;  call @put "there, in the shadows, stalking its prey (and next meal)."
call sy 'showing list'                      ;  call @show
call sy 'adding to head: Oy!'               ;  call @put  "Oy!",0
call sy 'showing list'                      ;  call @show
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
p:       return word(arg(1), 1)                  /*pick the first word out of many items*/
sy:      say;   say left('', 30) "───" arg(1) '───';              return
@init:   $.@=;    @adjust: $.@=space($.@);   $.#=words($.@);      return
@hasopt: arg o;                                                   return pos(o, opt)\==0
@size:   return $.#
/*──────────────────────────────────────────────────────────────────────────────────────*/
@del:    procedure expose $.;     arg k,m;          call @parms 'km'
         _=subword($.@, k, k-1)   subword($.@, k+m)
         $.@=_;                   call @adjust;                                return
/*──────────────────────────────────────────────────────────────────────────────────────*/
@get:    procedure expose $.;     arg k,m,dir,_
         call @parms 'kmd'
                                  do j=k  for m  by dir  while  j>0  &  j<=$.#
                                  _=_ subword($.@, j, 1)
                                  end   /*j*/
         return strip(_)
/*──────────────────────────────────────────────────────────────────────────────────────*/
@parms:  arg opt                                 /*define a variable based on an option.*/
         if @hasopt('k')  then k=min($.#+1, max(1, p(k 1)))
         if @hasopt('m')  then m=p(m 1)
         if @hasopt('d')  then dir=p(dir 1);                                   return
/*──────────────────────────────────────────────────────────────────────────────────────*/
@put:    procedure expose $.;     parse arg x,k;        k=p(k $.#+1);      call @parms 'k'
         $.@=subword($.@, 1, max(0, k-1))   x   subword($.@, k);           call @adjust
         return
/*──────────────────────────────────────────────────────────────────────────────────────*/
@show:   procedure expose $.;     parse arg k,m,dir;    if dir==-1  &  k==''   then k=$.#
         m=p(m $.#);              call @parms 'kmd';    say @get(k,m, dir);    return

output

                               ─── initializing the list. ───

                               ─── building list: Was it a cat I saw ───

                               ─── displaying list size. ───
list size=6

                               ─── forward list ───
Was it a cat I saw

                               ─── backward list ───
saw I cat a it Was

                               ─── showing 4th item ───
cat

                               ─── showing 6th & 6th items ───
I saw

                               ─── adding item before item 4: black ───

                               ─── showing list ───
Was it a black cat I saw

                               ─── adding to tail: there, in the ... ───

                               ─── showing list ───
Was it a black cat I saw there, in the shadows, stalking its prey (and next meal).

                               ─── adding to head: Oy! ───

                               ─── showing list ───
Oy! Was it a black cat I saw there, in the shadows, stalking its prey (and next meal). 

Ruby

Extending Singly-Linked List (element)#Ruby

class DListNode < ListNode
  attr_accessor :prev
  # accessors :succ and :value are inherited

  def initialize(value, prev=nil, succ=nil)
    @value = value
    @prev = prev
    @prev.succ = self if prev
    @succ = succ
    @succ.prev = self if succ
  end

  def self.from_values(*ary)
    ary << (f = ary.pop)
    ary.map! {|i| new i }
    ary.inject(f) {|p, c| p.succ = c; c.prev = p; c }
  end
end

list = DListNode.from_values 1,2,3,4

Rust

Simply using the standard library

use std::collections::LinkedList;
fn main() {
     // Doubly linked list containing 32-bit integers
     let list = LinkedList::<i32>::new();
}

The behind-the-scenes implementation

Doubly linked lists present a problem in Rust due to its ownership model. There cannot be two mutable references to the same object, so what are we to do? Below are the relevant lines (with added comments) from the std implementation (Documentation Source).

The standard library uses the (currently) unstable `Shared<T>` type which indicates that the ownership of its contained type has shared ownership. It is guaranteed not to be null, is variant over T (meaning that an &Shared<&'static T> may be used where a &Shared<&'a T> is expected, indicates to the compiler that it may own a T) and may be dereferenced to a mutable pointer (*mut T). All of the above may be accomplished in standard stable Rust, except for the non-null guarantee which allows the compiler to make a few extra optimizations.

pub struct LinkedList<T> {
    head: Option<Shared<Node<T>>>,
    tail: Option<Shared<Node<T>>>,
    len: usize,
    marker: PhantomData<Box<Node<T>>>, // Indicates that we logically own a boxed (owned pointer) Node<T>>
}

struct Node<T> {
    next: Option<Shared<Node<T>>>,
    prev: Option<Shared<Node<T>>>,
    element: T,
}

Sidef

var node = Hash.new(
     data => 'say what',
     next => foo_node,
     prev => bar_node,
);

node{:next} = quux_node;  # mutable

Swift

typealias NodePtr<T> = UnsafeMutablePointer<Node<T>>

class Node<T> {
  var value: T
  fileprivate var prev: NodePtr<T>?
  fileprivate var next: NodePtr<T>?

  init(value: T, prev: NodePtr<T>? = nil, next: NodePtr<T>? = nil) {
    self.value = value
    self.prev = prev
    self.next = next
  }
}

Tcl

Generally, this task should be accomplished in Tcl using list. Here we take an approach that's more comparable with the other examples on this page.
Works with: Tcl version 8.6

or

Library: TclOO
oo::class create List {
    variable content next prev
    constructor {value {list ""}} {
        set content $value
        set next $list
        set prev ""
        if {$next ne ""} {
            $next previous [self]
        }
    }
    method value args {
        set content {*}$args
    }
    method next args {
        set next {*}$args
    }
    method previous args {
        set prev {*}$args
    }
}

Visual Basic .NET

Public Class Node(Of T)
   Public Value As T
   Public [Next] As Node(Of T)
   Public Previous As Node(Of T)
End Class

Wren

Library: Wren-llist

The DNode class in the above module is the element type for the DLinkedList class which is a generic doubly-linked list. The latter is implemented in such a way that the user does not need to deal directly with DNode though for the purposes of the task we show below how instances of it can be created and manipulated.

import "./llist" for DNode

var dn1 = DNode.new(1)
var dn2 = DNode.new(2)
dn1.next = dn2
dn1.prev = null
dn2.prev = dn1
dn2.next = null
System.print(["node 1", "data = %(dn1.data)", "prev = %(dn1.prev)", "next = %(dn1.next)"])
System.print(["node 2", "data = %(dn2.data)", "prev = %(dn2.prev)", "next = %(dn2.next)"])
Output:
[node 1, data = 1, prev = null, next = 2]
[node 2, data = 2, prev = 1, next = null]

XPL0

def \Node\ Prev, Data, Next;    \Element (Node) definition

zkl

class Node{
   fcn init(_value,_prev=Void,_next=Void)
      { var value=_value, prev=_prev, next=_next; }
   fcn toString{ value.toString() }
}
a,b:=Node(1),Node("three");
a.next=b; b.prev=a;
println(a.next,"  ",b.prev);
Output:
three  1