Movatterモバイル変換


[0]ホーム

URL:


Jump to content
Rosetta Code
Search

Doubly-linked list/Element insertion

From Rosetta Code
<Doubly-linked list
Task
Doubly-linked list/Element insertion
You are encouraged tosolve this task according to the task description, using any language you may know.

Use the link structure defined inDoubly-Linked List (element) to define a procedure for inserting a link into a doubly-linked list. Call this procedure to insert element C into a list {A,B}, between elements A and B.

This is much like inserting into aSingly-Linked List, but with added assignments so that the backwards-pointing links remain correct.

See also

Action!

The user must type in the monitor the following command after compilation and before running the program!

SET EndProg=*
Library:Action! Tool Kit
CARD EndProg ;required for ALLOCATE.ACTINCLUDE "D2:ALLOCATE.ACT" ;from the Action! Tool Kit. You must type 'SET EndProg=*' from the monitor after compiling, but before running this program!DEFINE PTR="CARD"DEFINE NODE_SIZE="5"TYPE ListNode=[CHAR data PTR prv,nxt]ListNode POINTER listBegin,listEndPROC AddBegin(CHAR v)  ListNode POINTER n  n=Alloc(NODE_SIZE)  n.data=v  n.prv=0  n.nxt=listBegin  IF listBegin THEN    listBegin.prv=n  ELSE    listEnd=n  FI  listBegin=nRETURNPROC AddEnd(CHAR v)  ListNode POINTER n  n=Alloc(NODE_SIZE)  n.data=v  n.prv=listEnd  n.nxt=0  IF listEnd THEN    listEnd.nxt=n  ELSE    listBegin=n  FI  listEnd=nRETURNPROC AddAfter(CHAR v ListNode POINTER node)  ListNode POINTER n,tmp  IF node=0 THEN    PrintE("The node is null!") Break()  ELSEIF node=listEnd THEN    AddEnd(v)  ELSE    n=Alloc(NODE_SIZE)    n.data=v    n.nxt=node.nxt    n.prv=node    tmp=node.nxt    tmp.prv=n    node.nxt=n  FIRETURNPROC Clear()  ListNode POINTER n,next  n=listBegin  WHILE n  DO    next=n.nxt    Free(n,NODE_SIZE)    n=next  OD  listBegin=0  listEnd=0RETURNPROC PrintList()  ListNode POINTER n  n=listBegin  Print("(")  WHILE n  DO    Put(n.data)    IF n.nxt THEN      Print(", ")    FI    n=n.nxt  OD  PrintE(")")RETURNPROC TestAddBegin(CHAR v)  AddBegin(v)  PrintF("Add '%C' at the begin:%E",v)  PrintList()RETURNPROC TestAddAfter(CHAR v ListNode POINTER node)  AddAfter(v,node)  PrintF("Add '%C' after '%C':%E",v,node.data)  PrintList()RETURNPROC TestClear()  Clear()  PrintE("Clear the list:")  PrintList()RETURNPROC Main()  Put(125) PutE() ;clear screen    AllocInit(0)  listBegin=0  listEnd=0  PrintList()  TestAddBegin('A)  TestAddAfter('B,listBegin)  TestAddAfter('C,listBegin)  TestClear()RETURN
Output:

Screenshot from Atari 8-bit computer

()Add 'A' at the begin:(A)Add 'B' after 'A':(A, B)Add 'C' after 'A':(A, C, B)Clear the list:()

Ada

Define the procedure:

procedureInsert(Anchor:Link_Access;New_Link:Link_Access)isbeginifAnchor/=NullandNew_Link/=NullthenNew_Link.Next:=Anchor.Next;New_Link.Prev:=Anchor;ifNew_Link.Next/=NullthenNew_Link.Next.Prev:=New_Link;endif;Anchor.Next:=New_Link;endif;endInsert;

Create links and form the list.

procedureMake_ListisA,B,C:Link_Access;beginA:=newLink;B:=newLink;C:=newLink;A.Data:=1;B.Data:=2;C.Data:=2;Insert(Anchor=>A,New_Link=>B);-- The list is (A, B)Insert(Anchor=>A,New_Link=>C);-- The list is (A, C, B)endMake_List;

Element insertion using the generic doubly linked list defined in the standard Ada containers library.

withAda.Containers.Doubly_Linked_Lists;withAda.Text_Io;useAda.Text_Io;withAda.Strings.Unbounded;useAda.Strings.Unbounded;procedureList_InsertionispackageString_Listis newAda.Containers.Doubly_Linked_Lists(Unbounded_String);useString_List;procedurePrint(Position:Cursor)isbeginPut_Line(To_String(Element(Position)));endPrint;The_List:List;beginThe_List.Append(To_Unbounded_String("A"));The_List.Append(To_Unbounded_String("B"));The_List.Insert(Before=>The_List.Find(To_Unbounded_String("B")),New_Item=>To_Unbounded_String("C"));The_List.Iterate(Print'access);endList_Insertion;

ALGOL 68

Works with:ALGOL 68 version Revision 1 - no extensions to language used.
Works with:ALGOL 68G version Any - tested with release1.18.0-9h.tiny.
#!/usr/local/bin/a68g --script ## SEMA do link OF splice = LEVEL 1 #MODE LINK = STRUCT (  REF LINK prev,  REF LINK next,  DATA value);# BEGIN rosettacode task specimen code:  can handle insert both before the first, and after the last link #PROC insert after = (REF LINK #self,# prev, DATA new data)LINK: (# DOWN do link OF splice OF self; to make thread safe #  REF LINK next = next OF prev;  HEAP LINK new link := LINK(prev, next, new data);  next OF prev := prev OF next := new link;# UP do link OF splice OF self; #  new link);PROC insert before = (REF LINK #self,# next, DATA new data)LINK:  insert after(#self,# prev OF next, new data);# END rosettacode task specimen code ## Test case: #MODE DATA = STRUCT(INT year elected, STRING name);FORMAT data fmt = $dddd": "g"; "$;test:(# manually initialise the back splices #  LINK presidential splice;  presidential splice := (presidential splice, presidential splice, SKIP);# manually build the chain #  LINK previous, incumbent, elect;  previous := (presidential splice, incumbent,          DATA(1993, "Clinton"));  incumbent:= (previous,           elect,              DATA(2001, "Bush"   ));  elect    := (incumbent,          presidential splice, DATA(2008, "Obama"  ));  insert after(incumbent, LOC DATA := DATA(2004, "Cheney"));  REF LINK node := previous;  WHILE REF LINK(node) ISNT presidential splice DO    printf((data fmt, value OF node));    node := next OF node  OD;  print(new line))

Output:

1993: Clinton; 2001: Bush; 2004: Cheney; 2008: Obama;

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       %    % inserts a new element into the list, before e                           %    reference(DListIElement) procedure insertIntoDListIBefore( reference(DListIElement) value e                                                             ; integer                  value v                                                             );    begin        reference(DListIElement) newElement;        newElement := DListIElement( null, v, e );        if e not = null then begin            % the element we are inserting before is not null                 %            reference(DListIElement) ePrev;            ePrev            := prev(e);            prev(newElement) := ePrev;            prev(e)          := newElement;            if ePrev not = null then next(ePrev) := newElement        end if_e_ne_null ;        newElement    end insertIntoDListiAfter ;

AutoHotkey

seeDoubly-linked list/AutoHotkey

Axe

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

BBC BASIC

Works with:BBC BASIC for Windows
DIMnode{pPrev%,pNext%,iData%}DIMa{}=node{},b{}=node{},c{}=node{}a.pNext%=b{}a.iData%=123b.pPrev%=a{}b.iData%=456c.iData%=789PROCinsert(a{},c{})ENDDEFPROCinsert(here{},new{})LOCALtemp{}:DIMtemp{}=node{}new.pNext%=here.pNext%new.pPrev%=here{}!(^temp{}+4)=new.pNext%temp.pPrev%=new{}here.pNext%=new{}ENDPROC

C

Define the function:

voidinsert(link*anchor,link*newlink){newlink->next=anchor->next;newlink->prev=anchor;(newlink->next)->prev=newlink;anchor->next=newlink;}

Production code should also include checks that the passed links are valid (e.g. not null pointers). There should also be code to handle special cases, such as when *anchor is the end of the existing list (i.e. anchor->next is a null pointer).


To call the function:

Create links, and form the list:

linka,b,c;a.next=&b;a.prev=null;a.data=1;b.next=null;b.prev=&a;b.data=3;c.data=2;

This list is now {a,b}, and c is separate.

Now call the function:

insert(&a,&c);

This function call changes the list from {a,b} to {a,b,c}.

C#

The function handles creation of nodes in addition to inserting them.

staticvoidInsertAfter(Linkprev,inti){if(prev.next!=null){prev.next.prev=newLink(){item=i,prev=prev,next=prev.next};prev.next=prev.next.prev;}elseprev.next=newLink(){item=i,prev=prev};}

Example use:

staticvoidMain(){//Create A(5)->B(7)varA=newLink(){item=5};InsertAfter(A,7);//Insert C(15) between A and BInsertAfter(A,15);}

C++

C++ already has own linked list structure. If we were to roll our own linked list, we could implement function inserting new value after specific node like that:

template<typenameT>voidinsert_after(Node<T>*N,T&&data){autonode=newNode<T>{N,N->next,std::forward(data)};if(N->next!=nullptr)N->next->prev=node;N->next=node;}

Clojure

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

(defrecordNode[prevnextdata])(defnnew-node[prevnextdata](Node.(refprev)(refnext)data))(defnnew-list[headtail](List.(refhead)(reftail)))(defninsert-between[node1node2new-node](dosync(ref-set(:nextnode1)new-node)(ref-set(:prevnew-node)node1)(ref-set(:nextnew-node)node2)(ref-set(:prevnode2)new-node)))(set!*print-level*1);; warning: depending on the value of *print-level*;;   this could cause a stack overflow when printing(let[h(new-nodenilnil:A)t(new-nodenilnil:B)](insert-betweenht(new-nodenilnil:C))(new-listht))

Common Lisp

Code is on theDoubly-Linked List page, in functioninsert-between.

D

importstd.stdio;structNode(T){Tdata;typeof(this)*prev,next;}/// If prev is null, prev gets to point to a new node.voidinsertAfter(T)(refNode!T*prev,Titem)purenothrow{if(prev){autonewNode=newNode!T(item,prev,prev.next);prev.next=newNode;if(newNode.next)newNode.next.prev=newNode;}elseprev=newNode!T(item);}voidshow(T)(Node!T*list){while(list){write(list.data," ");list=list.next;}writeln;}voidmain(){Node!(string)*list;insertAfter(list,"A");list.show;insertAfter(list,"B");list.show;insertAfter(list,"C");list.show;}
Output:
A A B A C B

Delphi

Library: System.SysUtils
Library:Boost.LinkedList

[1]

programElement_insertion;{$APPTYPE CONSOLE}usesSystem.SysUtils,Boost.LinkedList;varList:TLinkedList<Integer>;Node:TLinkedListNode<Integer>;beginList:=TLinkedList<Integer>.Create;Node:=List.Add(5);List.AddAfter(Node,7);List.AddAfter(Node,15);Writeln(List.ToString);List.Free;Readln;end.
Output:
[ 5, 15, 7]

See#Pascal for vanilla version.

E

def insert(after, value) {    def newNode := makeElement(value, after, after.getNext())    after.getNext().setPrev(newNode)    after.setNext(newNode)}
insert(A_node, C)


Erlang

Using the code inDoubly-linked_list/Definition.

Output:
2> doubly_linked_list:task().foreach_next aforeach_next cforeach_next bforeach_previous bforeach_previous cforeach_previous a

Fortran

In ISO Fortran 95 or later:

moduledlListpublic::node,insertAfter,getNexttypenodereal::data        type(node),pointer::next=>null()type(node),pointer::previous=>null()end typenodecontains    subroutineinsertAfter(nodeBefore,value)type(node),intent(inout),target::nodeBeforetype(node),pointer::newNodereal,intent(in)::value        allocate(newNode)newNode%data=valuenewNode%next=>nodeBefore%nextnewNode%previous=>nodeBeforeif(associated(newNode%next))thennewNode%next%previous=>newNodeend ifnewNode%previous%next=>newNodeend subroutineinsertAftersubroutinedelete(current)type(node),intent(inout),pointer::currentif(associated(current%next))current%next%previous=>current%previousif(associated(current%previous))current%previous%next=>current%nextdeallocate(current)end subroutinedeleteend moduledlListprogramdlListTestusedlListtype(node),target::headtype(node),pointer::current,nexthead%data=1.0current=>headdoi=1,20callinsertAfter(current,2.0**i)current=>current%nextend docurrent=>headdo while(associated(current))print*,current%datanext=>current%nextif(.not.associated(current,head))calldelete(current)current=>nextend doend programdlListTest

Output:

1.2.4.8.16.32.64.128.256.512.1024.2048.4096.8192.16384.32768.65536.131072.262144.524288.1048576.


FreeBASIC

Translation of:Yabasic
#defineFIL1#defineDATO2#defineLPREV3#defineLNEXT4DimSharedAsIntegercountNodes,NodescountNodes=0Nodes=10DimSharedAsIntegerlist(Nodes,4)list(0,LNEXT)=1FunctionsearchNode(nodeAsInteger)AsIntegerDimAsIntegerNode11ForiAsInteger=0Tonode-1Node11=list(Node11,LNEXT)NextiReturnNode11EndFunctionSubinsertNode(nodeAsInteger,newNodeAsInteger)DimAsIntegerNode11,iIfcountNodes=0Thennode=2Fori=1ToNodesIfNotlist(i,FIL)ThenExitForNextlist(i,FIL)=Truelist(i,DATO)=newNodeNode11=searchNode(node)list(i,LPREV)=list(Node11,LPREV)list(list(i,LPREV),LNEXT)=iIfi<>Node11Thenlist(i,LNEXT)=Node11:list(Node11,LPREV)=icountNodes+=1IfcountNodes=NodesThenNodes+=10:Redimlist(Nodes,4)EndSubSubremoveNode(nAsInteger)DimAsIntegerNode11=searchNode(n)list(list(Node11,LPREV),LNEXT)=list(Node11,LNEXT)list(list(Node11,LNEXT),LPREV)=list(Node11,LPREV)list(Node11,LNEXT)=0list(Node11,LPREV)=0list(Node11,FIL)=FalsecountNodes-=1EndSubSubprintNode(nodeAsInteger)DimAsIntegerNode11=searchNode(node)Printlist(Node11,DATO);PrintEndSubSubtraverseList()ForiAsInteger=1TocountNodesprintNode(i)NextiEndSubinsertNode(1,1000)insertNode(2,2000)insertNode(2,3000)traverseList()removeNode(2)PrinttraverseList()Sleep
Output:
Igual que la entrada de Yabasic.


Go

packagemainimport"fmt"typedlNodestruct{stringnext,prev*dlNode}typedlListstruct{head,tail*dlNode}func(list*dlList)String()string{iflist.head==nil{returnfmt.Sprint(list.head)}r:="["+list.head.stringforp:=list.head.next;p!=nil;p=p.next{r+=" "+p.string}returnr+"]"}func(list*dlList)insertTail(node*dlNode){iflist.tail==nil{list.head=node}else{list.tail.next=node}node.next=nilnode.prev=list.taillist.tail=node}func(list*dlList)insertAfter(existing,insert*dlNode){insert.prev=existinginsert.next=existing.nextexisting.next.prev=insertexisting.next=insertifexisting==list.tail{list.tail=insert}}funcmain(){dll:=&dlList{}fmt.Println(dll)a:=&dlNode{string:"A"}dll.insertTail(a)dll.insertTail(&dlNode{string:"B"})fmt.Println(dll)dll.insertAfter(a,&dlNode{string:"C"})fmt.Println(dll)}

Output:

<nil>[A B][A C B]

Haskell

Using the algebraic data type and update functions fromDoubly-Linked_List_(element)#Haskell.

insert_Leaf=Leafinsertnvl@(Nodeplvr)=(\(Nodec__)->c)newwherenew=updateLeftleft.updateRightright$Nodelnvrleft=Nodeplvnewright=caserofLeaf->LeafNode_vr->Nodenewvr

Icon andUnicon

Uses Unicon classes.

classDoubleLink(value,prev_link,next_link)# insert given node after this one, losing its existing connectionsmethodinsert_after(node)node.prev_link:=selfif(\next_link)thennext_link.prev_link:=nodenode.next_link:=next_linkself.next_link:=nodeendinitially(value,prev_link,next_link)self.value:=valueself.prev_link:=prev_link# links are 'null' if not givenself.next_link:=next_linkend

J

Using the list element definition atDoubly-linked_list/Element_definition#J

 (pred;succ;<data) conew 'DoublyLinkedListElement'

This creates a new node containing the specified data between the nodes pred and succ.

Java

TheLinkedList<T> class is the Doubly-linked list implementation in Java. There are a large number of methods supporting the list.

The Java implementation does not a method to add an element based on another element. However, we can use methods from the base class to create aAddAfter method. A class with this method inherting all methods from theLinkedList<T> class is shown below.

importjava.util.LinkedList;@SuppressWarnings("serial")publicclassDoublyLinkedListInsertion<T>extendsLinkedList<T>{publicstaticvoidmain(String[]args){DoublyLinkedListInsertion<String>list=newDoublyLinkedListInsertion<String>();list.addFirst("Add First 1");list.addFirst("Add First 2");list.addFirst("Add First 3");list.addFirst("Add First 4");list.addFirst("Add First 5");traverseList(list);list.addAfter("Add First 3","Add New");traverseList(list);}/*     * Add after indicated node.  If not in the list, added as the last node.     */publicvoidaddAfter(Tafter,Telement){intindex=indexOf(after);if(index>=0){add(index+1,element);}else{addLast(element);}}privatestaticvoidtraverseList(LinkedList<String>list){System.out.println("Traverse List:");for(inti=0;i<list.size();i++){System.out.printf("Element number %d - Element value = '%s'%n",i,list.get(i));}System.out.println();}}
Output:
Traverse List:Element number 0 - Element value = 'Add First 5'Element number 1 - Element value = 'Add First 4'Element number 2 - Element value = 'Add First 3'Element number 3 - Element value = 'Add First 2'Element number 4 - Element value = 'Add First 1'Traverse List:Element number 0 - Element value = 'Add First 5'Element number 1 - Element value = 'Add First 4'Element number 2 - Element value = 'Add First 3'Element number 3 - Element value = 'Add New'Element number 4 - Element value = 'Add First 2'Element number 5 - Element value = 'Add First 1'

JavaScript

SeeDoubly-Linked_List_(element)#JavaScript

DoublyLinkedList.prototype.insertAfter=function(searchValue,nodeToInsert){if(this._value==searchValue){varafter=this.next();this.next(nodeToInsert);nodeToInsert.prev(this);nodeToInsert.next(after);after.prev(nodeToInsert);}elseif(this.next()==null)thrownewError(0,"value '"+searchValue+"' not found in linked list.")elsethis.next().insertAfter(searchValue,nodeToInsert);}varlist=createDoublyLinkedListFromArray(['A','B']);list.insertAfter('A',newDoublyLinkedList('C',null,null));

Julia

mutablestructDLNode{T}value::Tpred::Union{DLNode{T},Nothing}succ::Union{DLNode{T},Nothing}DLNode(v)=new{typeof(v)}(v,nothing,nothing)endfunctioninsertpost(prevnode,node)succ=prevnode.succprevnode.succ=nodenode.pred=prevnodenode.succ=succifsucc!=nothingsucc.pred=nodeendnodeendfunctionprintfromroot(root)print(root.value)whileroot.succ!=nothingroot=root.succprint(" ->$(root.value)")endprintln()endnode1=DLNode(1)printfromroot(node1)node2=DLNode(2)node3=DLNode(3)insertpost(node1,node2)printfromroot(node1)insertpost(node1,node3)printfromroot(node1)
Output:

11 -> 21 -> 3 -> 2

Kotlin

// version 1.1.2classNode<T:Number>(vardata:T,varprev:Node<T>?=null,varnext:Node<T>?=null){overridefuntoString():String{valsb=StringBuilder(this.data.toString())varnode=this.nextwhile(node!=null){sb.append(" -> ",node.data.toString())node=node.next}returnsb.toString()}}fun<T:Number>insert(after:Node<T>,new:Node<T>){new.next=after.nextif(after.next!=null)after.next!!.prev=newnew.prev=afterafter.next=new}funmain(args:Array<String>){vala=Node(1)valb=Node(3,a)a.next=bprintln("Before insertion : $a")valc=Node(2)insert(after=a,new=c)println("After  insertion : $a")}
Output:
Before insertion : 1 -> 3After  insertion : 1 -> 2 -> 3

Lua

seeDoubly-linked_list/Definition#Lua

Mathematica /Wolfram Language

ds=CreateDataStructure["DoublyLinkedList"];ds["Append","A"];ds["Append","B"];ds["Append","C"];ds["SwapPart",2,3];ds["Elements"]
Output:
{"A", "C", "B"}

Nim

procinsertAfter[T](l:varList[T],r,n:Node[T])=n.prev=rn.next=r.nextn.next.prev=nr.next=nifr==l.tail:l.tail=n

Oberon-2

PROCEDURE(dll:DLList)InsertAfter*(p:Node;o:Box.Object);VARn:Node;BEGINn:=NewNode(o);n.prev:=p;n.next:=p.next;IFp.next#NILTHENp.next.prev:=nEND;p.next:=n;IFp=dll.lastTHENdll.last:=nEND;INC(dll.size)ENDInsertAfter;

Objeck

method : public : native : AddBack(value : Base) ~ Nil {  node := ListNode->New(value);  if(@head = Nil) {    @head := node;    @tail := @head;  }  else {    @tail->SetNext(node);    node->SetPrevious(@tail);      @tail := node;  };}

OCaml

with dlink

(* val _insert : 'a dlink -> 'a dlink -> unit *)let_insertanchornewlink=newlink.next<-anchor.next;newlink.prev<-Someanchor;beginmatchnewlink.nextwith|None->()|Somenext->next.prev<-Somenewlink;end;anchor.next<-Somenewlink;;(* val insert : 'a dlink option -> 'a -> unit *)letinsertdlv=matchdlwith|(Someanchor)->_insertanchor{data=v;prev=None;next=None}|None->invalid_arg"dlink empty";;

testing in the top level:

#typet=A|B|C;;typet=A|B|C#letdl=dlink_of_list[A;B]ininsertdlC;list_of_dlinkdl;;-:tlist=[A;C;B]

with nav_list

(* val insert : 'a nav_list -> 'a -> 'a nav_list *)letinsert(prev,cur,next)v=(prev,cur,v::next)

testing in the top level:

#typet=A|B|C;;typet=A|B|C#letnl=nav_list_of_list[A;B];;valnl:'alist*t*tlist=([],A,[B])#insertnlC;;-:'alist*t*tlist=([],A,[C;B])

Oforth

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

: test      // ( -- aDList )| dl |   DList new ->dl   dl insertFront("A")    dl insertBack("B")   dl head insertAfter(DNode new("C", null , null))   dl ;
Output:
>test .s[1] (DList) [A, C, B]

Oz

Warning: Do not use in real programs.

declare  fun {CreateNewNode Value}     node(prev:{NewCell nil}          next:{NewCell nil}          value:Value)  end  proc {InsertAfter Node NewNode}     Next = Node.next  in     (NewNode.next) := @Next     (NewNode.prev) := Node     case @Next of nil then skip     [] node(prev:NextPrev ...) then        NextPrev := NewNode     end     Next := NewNode  end  A = {CreateNewNode a}  B = {CreateNewNode b}  C = {CreateNewNode c}in  {InsertAfter A B}  {InsertAfter A C}

Pascal

procedureinsert_link(a,b,c:link_ptr);begina^.next:=c;ifb<>nilthenb^.prev:=c;c^.next:=b;c^.prev:=a;end;

Actually, a more likely real world scenario is 'insert after A'. So...

procedurerealistic_insert_link(a,c:link_ptr);beginifa^.next<>nilthena^.next^.prev:=c;(* 'a^.next^' is another way of saying 'b', if b exists *)c^.next:=a^.next;a^.next:=c;c^.prev:=a;end;

PascalABC.NET

typeNode<T>=autoclassdata:T;prev,next:Node<T>;end;typeMyLinkedList<T>=classfirst,last:Node<T>;procedureAddLast(x:T);beginiffirst=nilthenbeginfirst:=newNode<T>(x,nil,nil);last:=firstendelsebeginvarp:=newNode<T>(x,last,nil);last.next:=p;last:=p;end;end;procedureAddAfter(p:Node<T>;x:T);beginiflast=pthenAddLast(x)elsebeginvarpp:=newNode<T>(x,p,p.next);p.next:=pp;pp.prev.next:=pp;endend;end;

Perl

my%node_model=(data=>'something',prev=>undef,next=>undef,);subinsert{my($anchor,$newlink)=@_;$newlink->{next}=$anchor->{next};$newlink->{prev}=$anchor;$newlink->{next}->{prev}=$newlink;$anchor->{next}=$newlink;}# create the list {A,B}my$node_a={%node_model};my$node_b={%node_model};$node_a->{next}=$node_b;$node_b->{prev}=$node_a;# insert element C into a list {A,B}, between elements A and B.my$node_c={%node_model};insert($node_a,$node_c);

Phix

See alsoDoubly-linked_list/Traversal.

enumNEXT,PREV,DATAconstantempty_dll={{1,1}}sequencedll=deep_copy(empty_dll)procedureinsert_after(objectdata,integerpos=1)integerprv=dll[pos][PREV]dll=append(dll,{pos,prv,data})ifprv!=0thendll[prv][NEXT]=length(dll)endifdll[pos][PREV]=length(dll)endprocedureinsert_after("ONE")insert_after("TWO")insert_after("THREE")?dll
Output:
{{2,4},{3,1,"ONE"},{4,2,"TWO"},{1,3,"THREE"}}

PicoLisp

This works with the structures described inDoubly-linked list/Definition#PicoLisp andDoubly-linked list/Element definition#PicoLisp.

# Insert an element X at position Pos(de 2insert (X Pos DLst)   (let (Lst (nth (car DLst) (dec (* 2 Pos)))  New (cons X (cadr Lst) Lst))      (if (cadr Lst)         (con (cdr @) New)         (set DLst New) )      (if (cdr Lst)         (set @ New)         (con DLst New) ) ) )(setq *DL (2list 'A 'B))      # Build a two-element doubly-linked list(2insert 'C 2 *DL)            # Insert C at position 2

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

PL/I

define structure   1 Node,      2 value        fixed decimal,      2 back_pointer handle(Node),      2 fwd_pointer  handle(Node);/* Given that 'Current" points at some node in the linked list :    */P = NEW (: Node :); /* Create a node. */get (P => value);P => fwd_pointer = Current => fwd_pointer;                    /* Points the new node at the next one.         */Current => fwd_pinter = P;                    /* Points the current node at the new one.      */P => back_pointer = Current;                    /* Points the new node back at the current one. */Q = P => fwd_pointer;Q => back_pointer = P;                    /* Points the next node to the new one.         */

Pop11

define insert_double(list, element);   lvars tmp;   if list == [] then      ;;; Insertion into empty list, return element      element   else      next(list) -> tmp;      list -> prev(element);      tmp -> next(element);      element -> next(list);      if tmp /= [] then         element -> prev(tmp)      endif;      ;;; return original list      list   endif;enddefine;lvars A = newLink(), B = newLink(), C = newLink();;;; Build the list of A and Binsert_double(A, B) -> _;;;; insert C between A and binsert_double(A, C) -> _;

PureBasic

Structurenode*prev.node*next.nodevalue.c;usecharactertypeforelementsinthisexampleEndStructureProcedureinsertAfter(element.c,*c.node);insertnewnode*nafternode*candsetit's value to elementProtected*n.node=AllocateMemory(SizeOf(node))If*n*n\value=element*n\prev=*cIf*c*n\next=*c\next*c\next=*nEndIfEndIfProcedureReturn*nEndProcedureProceduredisplayList(*dl.node)Protected*n.node=*dlRepeatPrint(Chr(*n\Value)+" ")*n=*n\nextUntil*n=#NullEndProcedureIfOpenConsole()Definedl.node,*n.node*n=insertAfter('A',dl)insertAfter('B',*n)insertAfter('C',*n)displayList(dl)Print(#CRLF$+#CRLF$+"Press ENTER to exit")Input()CloseConsole()EndIf

Sample output:

A C B

Python

definsert(anchor,new):new.next=anchor.nextnew.prev=anchoranchor.next.prev=newanchor.next=new

Racket

Code is on theDoubly-Linked List page, in functioninsert-between.

Raku

(formerly Perl 6)

Using the generic definitions fromDoubly-linked_list/Definition#Raku:

roleDLElem[::T] {hasDLElem[T]$.previsrw;hasDLElem[T]$.nextisrw;hasT$.payload =T;methodpre-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;    }methodpost-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;    }methoddelete {die"Can't delete a sentinel"unless$!prevand$!next;$!next.prev =$!prev;$!prev.next =$!next;# conveniently returns next element    }}roleDLList[::DLE] {hasDLE$.first;hasDLE$.last;submethodBUILD {$!first =DLE.new;$!last =DLE.new;$!first.next =$!last;$!last.prev =$!first;    }methodlist { ($!first.next, *.next ...^ !*.next).map: *.payload }methodreverse { ($!last.prev, *.prev ...^ !*.prev).map: *.payload }}classDLElem_StrdoesDLElem[Str] {}classDLList_StrdoesDLList[DLElem_Str] {}my$sdll =DLList_Str.new;my$b =$sdll.first.post-insert('A').post-insert('B');$b.pre-insert('C');say$sdll.list;# A C B
Output:
A C B

REXX

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

/*REXX program that implements various   List Manager   functions.      *//*┌────────────────────────────────────────────────────────────────────┐┌─┘                    Functions of the  List Manager                  └─┐│                                                                        ││ @init      ─── initializes the List.                                   ││                                                                        ││ @size      ─── returns the size of the List  [could be  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.          │└─┐                                                                    ┌─┘  └────────────────────────────────────────────────────────────────────┘*/callsy'initializing the list.';call@initcallsy'building list: Was it a cat I saw';call@put'Was it a cat I saw'callsy'displaying list size.';say'list size='@size()callsy'forward list';call@showcallsy'backward list';call@show,,-1callsy'showing 4th item';call@show4,1callsy'showing 6th & 6th items';call@show5,2callsy'adding item before item 4: black';call@put'black',4callsy'showing list';call@showcallsy'adding to tail: there, in the ...';call@put'there, in the shadows, stalking its prey (and next meal).'callsy'showing list';call@showcallsy'adding to head: Oy!';call@put'Oy!',0callsy'showing list';call@showexit/*stick a fork in it, we're done.*//*──────────────────────────────────subroutines─────────────────────────*/p:returnword(arg(1),1)sy:say;sayleft('',30)"───"arg(1)'───';return@hasopt:argo;returnpos(o,opt)\==0@size:return$.#@init:$.@='';$.#=0;return0@adjust:$.@=space($.@);$.#=words($.@);return0@parms:argoptif@hasopt('k')thenk=min($.#+1,max(1,p(k1)))if@hasopt('m')thenm=p(m1)if@hasopt('d')thendir=p(dir1)return@show:procedureexpose$.;parseargk,m,dirifdir==-1&k==''thenk=$.#m=p(m$.#);call@parms'kmd'say@get(k,m,dir);return0@get:procedureexpose$.;argk,m,dir,_call@parms'kmd'doj=kformbydirwhilej>0&j<=$.#_=_subword($.@,j,1)end/*j*/returnstrip(_)@put:procedureexpose$.;parseargx,kk=p(k$.#+1)call@parms'k'$.@=subword($.@,1,max(0,k-1))xsubword($.@,k)call@adjustreturn0@del:procedureexpose$.;argk,mcall@parms'km'_=subword($.@,k,k-1)subword($.@,k+m)$.@=_call@adjustreturn

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

classDListNodedefinsert_after(search_value,new_value)ifsearch_value==valuenew_node=self.class.new(new_value,nil,nil)next_node=self.succself.succ=new_nodenew_node.prev=selfnew_node.succ=next_nodenext_node.prev=new_nodeelsifself.succ.nil?raiseStandardError,"value#{search_value} not found in list"elseself.succ.insert_after(search_value,new_value)endendendhead=DListNode.from_array([:a,:b])head.insert_after(:a,:c)

Rust

Doubly-linked list/Definition#Rust defines a method onLinkedList that inserts an element at an arbitrary index. The current task, however, asks us to insert aNode into the list which if you refer toDoubly-linked list/Element definition is not possible directly.

This is where we introduce the Cursor API. The cursor acts as a reference to anyNode that can also cycle around ourLinkedList by pointing to a sentinelNode located logically after the tail and before the head (represented byNone).

#![feature(linked_list_cursors)]pubstructCursor<'a,T:'a>{index:usize,current:Option<NonNull<Node<T>>>,list:&'aLinkedList<T>,}pubstructCursorMut<'a,T:'a>{index:usize,current:Option<NonNull<Node<T>>>,list:&'amutLinkedList<T>,}

We can write a function that moves the cursor up/down the list until it finds the first occurrence of a value, or until it reaches the sentinel if it doesn't find our value. Since for this example we're looking to insert a newNode, thus mutating the list, we'll only define the procedure forCursorMut.

#![feature(linked_list_cursors)]traitCursorExt<T>{fninsert_between(&mutself,l:&T,elt:T,r:&T);fnrinsert_between(&mutself,l:&T,elt:T,r:&T);}impl<T:PartialEq>CursorExt<T>forstd::collections::linked_list::CursorMut<'_,T>{fninsert_between(&mutself,l:&T,elt:T,r:&T){// Pointing at the sentinel, move to headifself.current().is_none(){self.move_next();}letnext=|cursor:&mutSelf|{letleft=cursor.current()?==a;letright=cursor.peek_next()?==b;Some(left&&right)};whileletSome(found)=next(self){iffound{self.insert_after(elt);return;}}}fnrinsert_between(&mutself,l:&T,elt:T,r:&T){// Pointing at the sentinel, move to tailifself.current().is_none(){self.move_prev();}letprev=|cursor:&mutSelf|{letleft=cursor.peek_prev()?==a;letright=cursor.current()?==b;Some(left&&right)};whileletSome(found)=prev(self){iffound{self.insert_before(elt);return;}}}}fnelement_insertion(){usestd::collections::LinkedList;letmutlist=LinkedList::from(['A','B']);list.cursor_front_mut().insert_between(&'A','C',&'B');// list.cursor_back_mut().rinsert_between(&'A', 'C', &'B');assert_eq!(list,['A','C','B'].into());}

Swift

typealiasNodePtr<T>=UnsafeMutablePointer<Node<T>>classNode<T>{varvalue:Tfileprivatevarprev:NodePtr<T>?fileprivatevarnext:NodePtr<T>?init(value:T,prev:NodePtr<T>?=nil,next:NodePtr<T>?=nil){self.value=valueself.prev=prevself.next=next}}@discardableResultfuncinsert<T>(_val:T,after:Node<T>?=nil,list:NodePtr<T>?=nil)->NodePtr<T>{letnode=NodePtr<T>.allocate(capacity:1)node.initialize(to:Node(value:val))varn=listwhilen!=nil{ifn?.pointee!==after{n=n?.pointee.nextcontinue}node.pointee.prev=nnode.pointee.next=n?.pointee.nextn?.pointee.next?.pointee.prev=noden?.pointee.next=nodebreak}returnnode}// [1]letlist=insert(1)// [1, 2]insert(2,after:list.pointee,list:list)// [1, 3, 2]insert(3,after:list.pointee,list:list)

Tcl

SeeDoubly-Linked List (element) for caveats about linked lists in Tcl.

Works with:Tcl version 8.6
oo::defineList{methodinsertBefore{elem}{$elemnext[self]$elemprevious$previf{$prevne""}{$prevnext$elem}setprev$elem}methodinsertAfter{elem}{$elemprevious[self]$elemnext$nextif{$nextne""}{$nextprevious$elem}setnext$elem}}

Demonstration:

setB[Listnew3]setA[Listnew1$B]setC[Listnew2]$AinsertAfter$Cputs[format"{%d,%d,%d}"[$Avalue][[$Anext]value][[[$Anext]next]value]]

Visual Basic .NET

PublicSubInsert(ByValaAsNode(OfT),ByValbAsNode(OfT),ByValcAsT)DimnodeAsNewNode(OfT)(value)a.Next=nodenode.Previous=ab.Previous=nodenode.Next=bEndSub

Wren

Library:Wren-llist
import"./llist"forDLinkedListvardll=DLinkedList.new(["A","B"])dll.insertAfter("A","C")System.print(dll)
Output:
[A <-> C <-> B]

XPL0

def \Node\ Prev, Data, Next;    \Element (Node) definition    proc Insert(NewNode, Node);     \Insert NewNode after Node    int  NewNode, Node, NextNode;    [NextNode:= Node(Next);    NextNode(Prev):= NewNode;    NewNode(Next):= NextNode;    NewNode(Prev):= Node;    Node(Next):= NewNode;    ];int Node, A(3), B(3), C(3);[A(Next):= B;A(Data):= ^a;B(Prev):= A;B(Data):= ^b;B(Next):= 0;C(Data):= ^c;Insert(C, A);Node:= A;while Node # 0 do    [ChOut(0, Node(Data));    Node:= Node(Next);    ];]
Output:
acb

Yabasic

// Rosetta Code problem: http://rosettacode.org/wiki/Doubly-linked_list/Element_insertion & removal & traverse// by Galileo, 02/2022FIL = 1 : DATO = 2 : LPREV = 3 : LNEXT = 4countNodes = 0 : Nodes = 10dim list(Nodes, 4)list(0, LNEXT) = 1sub searchNode(node)    local i, Node        for i = 0 to node-1        Node = list(Node, LNEXT)    next    return Nodeend subsub insertNode(node, newNode)    local Node, i        if not countNodes node = 2        for i = 1 to Nodes        if not list(i, FIL) break    next    list(i, FIL) = true    list(i, DATO) = newNode            Node = searchNode(node)        list(i, LPREV) = list(Node, LPREV) : list(list(i, LPREV), LNEXT) = i    if i <> Node list(i, LNEXT) = Node : list(Node, LPREV) = i        countNodes = countNodes + 1    if countNodes = Nodes then Nodes = Nodes + 10 : redim list(Nodes, 4) : end ifend subsub removeNode(n)    local Node        Node = searchNode(n)    list(list(Node, LPREV), LNEXT) = list(Node, LNEXT)    list(list(Node, LNEXT), LPREV) = list(Node, LPREV)    list(Node, LNEXT) = 0 : list(Node, LPREV) = 0    list(Node, FIL) = false    countNodes = countNodes - 1end subsub printNode(node)    local Node        Node = searchNode(node)    print list(Node, DATO);    printend subsub traverseList()    local i        for i = 1 to countNodes        printNode(i)    nextend subinsertNode(1, 1000)insertNode(2, 2000)insertNode(2, 3000)traverseList()removeNode(2)printtraverseList()
Output:
10003000200010002000---Program done, press RETURN---

zkl

class Node{   fcn init(_value,_prev=Void,_next=Void)      { var value=_value, prev=_prev, next=_next; }   fcn toString{ value.toString() }   fcn append(value){      b,c := Node(value,self,next),next;      next=b;      if(c) c.prev=b;      b   }}
a:=Node("a"); a.append("b").append("c");println(a,"  ",a.next,"  ",a.next.next);
Output:
a  b  c
Retrieved from "https://rosettacode.org/wiki/Doubly-linked_list/Element_insertion?oldid=380694"
Categories:
Hidden category:
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

[8]ページ先頭

©2009-2025 Movatter.jp