Singly-linked list/Element definition: Difference between revisions
added scheme |
|||
Line 256: | Line 256: | ||
include Enumerable |
include Enumerable |
||
end |
end |
||
=={{header|Scheme}}== |
|||
Scheme, like other Lisp dialects, has extensive support for singly-linked lists. The element of such a list is known as a ''cons-pair'', because you use the <code>cons</code> function to construct it: |
|||
<scheme>(cons value next)</scheme> |
|||
The value and next-link parts of the pair can be deconstructed using the <code>car</code> and <code>cdr</code> functions, respectively: |
|||
<scheme>(car my-list) ; returns the first element of the list |
|||
(cdr my-list) ; returns the remainder of the list</scheme> |
|||
Each of these parts are mutable and can be set using the <code>set-car!</code> and <code>set-cdr!</code> functions, respectively: |
|||
<scheme>(set-car! my-list new-elem) |
|||
(set-cdr! my-list new-next)</scheme> |
Revision as of 04:53, 18 August 2008
You are encouraged to solve this task according to the task description, using any language you may know.
Define the data structure for a singly-linked list element. Said element should contain a data member capable of holding a numeric value, and the link to the next element should be mutable.
Ada
type Link; type Link_Access is access Link; type Link is record Next : Link_Access := null; Data : Integer; end record;
C
struct link { struct link *next; int data; };
C++
The simplest C++ version looks basically like the C version:
struct link { link* next; int data; };
Initialization of links on the heap can be simplified by adding a constructor:
struct link { link* next; int data; link(int a_data, link* a_next = 0): next(a_next), data(a_data) {} };
With this constructor, new nodes can be initialized directly at allocation; e.g. the following code creates a complete list with just one statement:
link* small_primes = new link(2, new link(3, new link(5, new link(7))));
However, C++ also allows to make it generic on the data type (e.g. if you need large numbers, you might want to use a larger type than int, e.g. long on 64-bit platforms, long long on compilers that support it, or even a bigint class).
template<typename T> struct link { link* next; T data; link(T a_data, link* a_next = 0): next(a_next), data(a_data) {} };
Note that the generic version works for any type, not only integral types.
Clean
import StdMaybe :: Link t = { next :: Maybe (Link t), data :: t }
Delphi
A simple one way list. I use a generic pointer for the data that way it can point to any structure, individual variable or whatever. Note that in Standard Pascal, there are no generic pointers, therefore one has to settle for a specific data type there.
Type pOneWayList = ^OneWayList; OneWayList = record pData : pointer ; Next : pOneWayList ; end;
E
interface LinkedList guards LinkedListStamp {} def empty implements LinkedListStamp { to null() { return true } } def makeLink(value :int, var next :LinkedList) { def link implements LinkedListStamp { to null() { return false } to value() { return value } to next() { return next } to setNext(new) { next := new } } return link }
Forth
Forth has no "struct" facility, but you can easily implement a single linked list with a data cell using a double-cell value.
: >cell-link ( a -- a ) ; : >cell-data ( a -- b ) cell+ ;
As an example of usage, here is a word to link 'a' after 'b'
: chain ( a b -- ) \ links 'a' after 'b' over >r dup >cell-link @ r> >cell-link ! \ a points at b's old link >cell-link ! ;
Or with named parameters:
: chain { a b -- } b >cell-link @ a >cell-link ! a b >cell-link ! ;
Due to Forth's lack of typechecking, 'b' in the above examples does not have to be an actual cell, but can instead be the head pointer of the list.
Fortran
In ISO Fortran 95 or later:
type node real :: data type( node ), pointer :: next => null() end type node ! !. . . . ! type( node ) :: head
Haskell
This task is not idiomatic for Haskell. Usually, all data in pure functional programming is immutable, and deconstructed through Pattern Matching. The Prelude already contains a parametrically polymorphic list type that can take any data member type, including numeric values. These lists are then used very frequently. Because of this, lists have additional special syntactic sugar.
An equivalent declaration for such a list type without the special syntax would look like this:
data List a = Nil | Cons a (List a)
A declaration like the one required in the task, with an integer as element type and a mutable link, would be
data IntList s = Nil | Cons Integer (STRef s (IntList s))
but that would be really awkward to use.
Java
The simplest Java version looks basically like the C++ version:
class Link { Link next; int data; }
Initialization of links on the heap can be simplified by adding a constructor:
class Link { Link next; int data; Link(int a_data, Link a_next) { next = a_next; data = a_data; } }
With this constructor, new nodes can be initialized directly at allocation; e.g. the following code creates a complete list with just one statement:
Link small_primes = new Link(2, new Link(3, new Link(5, new Link(7, null))));
However, Java also allows to make it generic on the data type. This will only work on reference types, not primitive types like int or float (wrapper classes like Integer and Float are available).
class Link<T> { Link<T> next; T data; Link(T a_data, Link<T> a_next) { next = a_next; data = a_data; } }
OCaml
This task is not idiomatic for OCaml. OCaml already contains a built-in parametrically polymorphic list type that can take any data member type, including numeric values. These lists are then used very frequently. Because of this, lists have additional special syntactic sugar. OCaml's built-in lists, like most functional data structures, are immutable, and are deconstructed through Pattern Matching.
An equivalent declaration for such a list type without the special syntax would look like this:
type 'a list = Nil | Cons of 'a * 'a list
A declaration like the one required in the task, with an integer as element type and a mutable link, would be
type int_list = Nil | Cons of int * int_list ref
but that would be really awkward to use.
Perl
Just use an array. You can traverse and splice it any way. Linked lists are way too low level.
However, if all you got is an algorithm in a foreign language, you can use references to accomplish the translation.
my %node = ( data => 'say what', next => \%foo_node, ); $node{next} = \%bar_node; # mutable
Pop11
List are built in into Pop11, so normally on would just use them:
;;; Use shorthand syntax to create list. lvars l1 = [1 2 three 'four']; ;;; Allocate a single list node, with value field 1 and the link field ;;; pointing to empty list lvars l2 = cons(1, []); ;;; print first element of l1 front(l1) => ;;; print the rest of l1 back(l1) => ;;; Use index notation to access third element l1(3) => ;;; modify link field of l2 to point to l1 l1 -> back(l2); ;;; Print l2 l2 =>
If however one wants to definite equivalent user-defined type, one can do this:
uses objectclass; define :class ListNode; slot value = []; slot next = []; enddefine; ;;; Allocate new node and assign to l1 newListNode() -> l1; ;;; Print it l1 => ;;; modify value 1 -> value(l1); l1 => ;;; Allocate new node with initialized values and assign to link field ;;; of l1 consListNode(2, []) -> next(l1); l1 =>
Python
The Node class implements also iteration for more Pythonic iteration over linked lists.
class Node: def __init__(self, value, next=None): self.value = value self.next = next def __iter__(self): node = self while node: yield node node = node.next
Ruby
class ListNode attr_accessor :value, :succ def initialize(v,s=nil) self.value=v self.succ=s end def each(&b) yield value succ.each(&b) if succ end include Enumerable end
Scheme
Scheme, like other Lisp dialects, has extensive support for singly-linked lists. The element of such a list is known as a cons-pair, because you use the cons
function to construct it:
<scheme>(cons value next)</scheme>
The value and next-link parts of the pair can be deconstructed using the car
and cdr
functions, respectively:
<scheme>(car my-list) ; returns the first element of the list
(cdr my-list) ; returns the remainder of the list</scheme>
Each of these parts are mutable and can be set using the set-car!
and set-cdr!
functions, respectively:
<scheme>(set-car! my-list new-elem)
(set-cdr! my-list new-next)</scheme>