Disentangle doubly linked data

Haskell, 79 65 59 55 bytes

-6 bytes thanks to Brute Force.

x#i|let-1!d=[];i!d=i:x!!i!!d!d=[x!!i!!1|i<-last(i!0)!2]

Defines function # that accepts a list of lists of integers, where null is represented as -1, and returns list of node values.

Try it online!

Explanation

let-1!d=[];i!d=i:x!!i!!d!d

Define function ! that iterates through the nodes starting at node i and returns a list visited indexes. It accepts the second argument d that specifies which index of the "tuple" use as the index of the next node (d==2 to iterate forwards, d==0 to iterate backwards).

(i!0)

Iterate backwards starting from the given index and return visited indexes.

last(i!0)

Take last visited index, which is the beginning of the list.

last(i!0)!2

Iterate from the beginning of the list.

[x!!i!!1|i<-last(i!0)!2]

Replace each visited index with the value of the node.


Python 2, 60 bytes

l,n=input()
while~n:m=n;n=l[n][0]
while~m:p,v,m=l[m];print v

Try it online!

This is pretty much Chas Brown's answer, minus these golfs:

  • I reuse n, saving an assignment
  • I store the last valid n in m, allowing me to
  • place the print after the assignment in line 3, saving me the final print
  • I use only ~n instead of -~n, because negative values are just as truthy as positive ones, saving me 2 characters.

Clean, 94 90 88 bytes

import StdEnv
$l[_,u,v]|v<0=[u]=[u: $l(l!!v)]
?l= $l o until((>)0o hd)((!!)l o hd)o(!!)l

Try it online!