解开双链接数据


12

双向链接列表是一种数据结构,其中每个节点都具有value指向列表中的previous和的“链接” nodes。例如,考虑以下具有值12、99和37的节点:

在此,值为1299的节点指向其各自的next值为9937的节点。值为37的节点没有next指针,因为它是列表中的最后一个节点。同样,值分别为9937的节点指向它们各自的previous节点1299,但是12没有previous指针,因为它是列表中的第一个节点。

设置

实际上,节点的“链接”被实现为指向内存中上一个和下一个节点位置的指针。对于我们的目的,“内存”将是节点的数组,而节点的位置将是其在数组中的索引。节点可以认为是形式的3元组( prev value next )。那么,上面的示例可能如下所示:

但它看起来可能像这样:

从任何节点开始,您可以跟随previous链接(显示为红色箭头的起点)到达其之前的节点,并跟随链接(next绿色箭头)以查找后续节点,以便按顺序获取所有节点的值:[12, 99, 37]

上面的第一个图可以用数组表示[[null, 12, 1], [0, 99, 2], [1, 37, null]]。那么第二个是[[2, 99, 1], [0, 37, null], [null, 12, 0]]

挑战

编写一个程序,该程序将节点数组和节点索引作为输入,并以列表顺序返回同一双链表中节点的值。

并发症

“内存”并不总是只包含一个列表的节点。它可能包含几个列表:

上面的数组包含三个双向链接列表,为方便起见用颜色编码:

  1. 在索引节点71014312(只显示next链接,以减少混乱;点击放大):

    给定此数组和所有这些索引,您的程序应按顺序返回values [0, 1, 1, 2, 3, 5, 8]

  2. 索引处的节点9

    给定索引9,您的程序应返回[99]

  3. 在索引节点118062

    给定这些索引之一,它应该返回[2, 3, 5, 7, 11]

规则

输入值

您的程序将收到以下输入:

  1. 𝒏个节点的列表(如上所述,三元组),其中1≤𝒏≤1,000,采用任何方便的格式,例如,数组数组,长度为3𝒏的整数的“扁平”数组等。

    的3元组的元件可以以任何顺序:( prev value next )( next prev value ),等。对于每个节点,prevnext将是null(或另一种方便的值,例如-1),表明在双重链接列表中的第一或最后一个节点,或所述有效的索引列表,可以方便地从0或1开始。value将是有符号的32位整数或您的语言支持的最大整数类型,以较小者为准。

  2. 列表中节点的索引((1)。所指示的节点可以是双向链表中的第一个节点,最后一个节点,中间节点,甚至是唯一节点。

输入列表(1)可能包含病理数据(例如,周期,多个其他节点指向的节点等),但是输入索引(2)始终指向一个节点,可以从该节点获得格式正确的单个输出推论。

输出量

您的程序应按列表顺序输出双向链接列表的节点的值,其中索引𝒑的节点是其成员。输出可以采用任何方便的格式,但是其数据必须仅包含node value

获奖

这是。以字节为单位的最短答案将获胜。有标准漏洞。

测试用例

下面,每个测试用例的形式为:

X)
prev value next, prev value next, ...
index
value value value ...

...其中X有一个字母表示测试用例,第二行是输入列表,第三行是从0开始的输入索引,第四行是输出。

A) null 12 1, 0 99 2, 1 37 null
   1
   12 99 37

B) 2 99 1, 0 37 null, null 12 0
   1
   12 99 37

C) 8 5 6, 10 1 4, 6 11 null, 4 3 12, 1 2 3, 12 8 null, 0 7 2, null 0 10, 11 3 0, null 99 null, 7 1 1, null 2 8, 3 5 5
   4
   0 1 1 2 3 5 8

D) 8 5 6, 10 1 4, 6 11 null, 4 3 12, 1 2 3, 12 8 null, 0 7 2, null 0 10, 11 3 0, null 99 null, 7 1 1, null 2 8, 3 5 5
   0
   2 3 5 7 11

E) 8 5 6, 10 1 4, 6 11 null, 4 3 12, 1 2 3, 12 8 null, 0 7 2, null 0 10, 11 3 0, null 99 null, 7 1 1, null 2 8, 3 5 5
   9
   99

F) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   18
   80 80 67 71

G) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   8
   1 -1 1 -1 1 -1 1

H) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   4
   1 3 6 10 15 21

I) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   14
   3 1 4 1 5 9 2 6 5 3

J) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   17
   8 6 7 5 3 0 9

K) 4 11 0, null 22 3, null 33 3, 1 44 4, 3 55 null, 7 66 7, 6 77 6
   3
   22 44 55

L) null -123 null
   0
   -123



是允许输入为三个数组(一个数组按顺序包含所有前任节点,一个值和一个后继节点),还是与元组的概念相距太远?
桑契斯

@Sanchises对不起,对我来说太过分了。
约旦

没关系!我是这么认为的,但是我想在我的答案之前发表任何评论,说我可以将两个字节分离为单独的数组。
桑契斯

Answers:


1

05AB1E,25个字节

è[¬D0‹#Isè]\[`sˆD0‹#Isè]¯

在线尝试!

说明

è[¬D0‹#Isè]\[`sˆD0‹#Isè]¯   # Arguments n, a
è                           # Get element at index n in a
 [¬D0‹#Isè]                 # Find the first element in the list
 [                          # While true, do
  ¬                         #   Head (get index of previous element)
   D0‹#                     #   Break if lower than 0
       Isè                  #   Get the element at that index
          ]                 # End loop
           \                # Delete top element of stack
            [`sˆD0‹#Isè]    # Iterate through list
            [               # While true, do
             `sˆ            #   Add value to global array and keep next index on stack
                D0‹#Isè     #   Same as above
                       ]    # End loop
                        ¯   # Push global array

3

Haskell79 65 59 55字节

-6个字节,多亏了蛮力

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

定义#接受整数列表的函数,其中null表示为-1,并返回节点值列表。

在线尝试!

说明

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

定义!从节点开始遍历节点i并返回访问列表的索引的函数。它接受第二个参数d,该参数指定“元组”的哪个索引用作下一个节点的索引(d==2向前d==0迭代,向后迭代)。

(i!0)

从给定索引开始向后迭代,并返回访问的索引。

last(i!0)

获取上次访问的索引,它是列表的开始。

last(i!0)!2

从列表的开头进行迭代。

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

将每个访问的索引替换为节点的值。


几乎可以将其写x!!i!!1i!1!!1,但由于-1输出而中断。如果您只是选择另一个哨兵值来表示null(例如-9),它会起作用,但是对于某些输入它总是会中断,这很烦人。
林恩

3

Python 2,60个字节

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

在线尝试!

减去这些高尔夫球,这几乎就是查斯·布朗的答案:

  • 我重复使用n,保存任务
  • 我将最后一个有效n存储在m中,以便
  • 将打印后的作业放在第3行中,为我保存了最终的打印稿
  • 我只使用〜n而不是-〜n,因为负值与正值一样真实,为我节省了2个字符。


2

MATL,39个字节

XHx`HwI3$)t]x6Mt`Hwl3$)tbhwt]x4L)Hw2I$)

在线尝试!

我的Octave答案几乎是直接端口,但此版本先找到结尾,然后再回溯,而不是相反,这样节省了一个字节。

XHx           % Store array in H.
`HwI3$)t]     % Work to the end of the array
x6Mt          % Delete the end of array delimiter, and push the array end index twice
`Hwl3$)    t] % Work to the beginning of the array
       tbhw   % Append all indices found.
Hw2I$)        % Index into original array.

1

PHP,132字节

<?list(,$x,$y)=$argv;parse_str($x);while(($q=$x[$y*3+1])>=0)$y=$q;do{$n[]=$x[$y*3+2];$y=$x[$y*3];}while($x[$y*3]);echo join(' ',$n);

在线尝试!

输入被作为查询字符串x[]=-1&x[]=1&x[]=1...(在一个平面阵列中的所有节点),在顺序nextprev,然后value用于与-1每个节点用于结束节点。


1

Python 2中81 77个字节

a,n=input()
u=a[n][0]
while-~u:u,v,w=a[u]
while-~w:print v;u,v,w=a[w]
print v

在线尝试!

编辑:Thx先生Xcoder为4个字节...

取元组[u,v,w]的列表,其中u和w为-1,以表示链接列表段的开始/结束。


77个字节在线尝试!。布尔值是int的子类,所以Falsy才是布尔0值,因此u>=0可以使用Boolean,u+1并且可以将其进一步缩短-~u以除去空白。
Xcoder先生17年

@先生。Xcoder-是的,完全正确!
Chas Brown

1

八度81 78 76字节

function o=f(a,n)while q=a(n,1)o=a(n=q,2);end
while n=a(n,3)o=[o a(n,2)];end

在线尝试!

相当简单的版本。解释留给读者练习。下面提供了一个更有趣的版本:

八度142 99 92字节

@(a,n)[(p=@(b,c,z){q=a(z,2),@()[b(b,c,a(z,c)),q]}{2-~a(z,c)}())(p,1,n),p(p,3,n)(end-1:-1:1)]

在线尝试!

哟,听说您喜欢匿名功能...

接受一个nx3数组,第一列为前任节点,第二列为前值,第三列为后继节点。所有节点索引均基于1,这是Octave中的默认值。

% Create an anonymous function, taking an array a and first node n
@(a,n)
% Returns an array containing the predecessor and sucessor nodes
      [                                                                     ,                     ]
% Defines an recursive anonymous function (by supplying itself to the local namespace)
% which looks at the first column (c=1) or last column (c=3) of the input array to get the next nodes
       (p=@(p,c,z)                                                   )(p,1,n)
% Create a cell array, either containing the end node,
                    {q=a(z,2),                       
% ...or an array with all next  next nodes and the current node
% (note the use of an anonymous function taking no parameters to defer array access, in case of the last node)                
                              @()[p(p,c,a(z,c)),q]}
% depending whether the next node number is nonzero (followed by () to execute the deferred array access)
                                                    {2-~a(z,c)}()
% Do the same with c=3, reverse (function p builds the array right-to-left) and drop the current node to prevent a duplicate.                                                                             
                                                                             p(p,3,n)(end-1:-1:1)

1

Kotlin,85个字节

{g,S->generateSequence(generateSequence(S){g[it][0]}.last()){g[it][2]}.map{g[it][1]}}

美化

{g,S->
    generateSequence(generateSequence(S){g[it][0]}.last()){ g[it][2]}.map { g[it][1] }
}

测试

typealias Node=Triple<Int?,Int?,Int?>
data class Test(val input: List<Node>, val start:Int, val result: List<Int>)
val TEST = listOf<Test>(
Test(
listOf(Node(null, 12, 1), Node(0, 99, 2), Node(1, 37, null)),
1,
listOf(12, 99, 37)
),
Test(listOf(
Node(2, 99, 1), Node(0, 37, null), Node(null, 12, 0)),
1,
listOf(12, 99, 37)
),
Test(
listOf(Node(8, 5, 6), Node(10, 1, 4), Node(6, 11, null), Node(4, 3, 12), Node(1, 2, 3), Node(12, 8, null), Node(0, 7, 2), Node(null, 0, 10), Node(11, 3, 0), Node(null, 99, null), Node(7, 1, 1), Node(null, 2, 8), Node(3, 5, 5)),
4,
listOf(0, 1, 1, 2, 3, 5, 8)
),
Test(
listOf(Node(8, 5, 6), Node(10, 1, 4), Node(6, 11, null), Node(4, 3, 12), Node(1, 2, 3), Node(12, 8, null), Node(0, 7, 2), Node(null, 0, 10), Node(11, 3, 0), Node(null, 99, null), Node(7, 1, 1), Node(null, 2, 8), Node(3, 5, 5)),
0,
listOf(2, 3, 5, 7, 11)
),
Test(
listOf(Node(8, 5, 6), Node(10, 1, 4), Node(6, 11, null), Node(4, 3, 12), Node(1, 2, 3), Node(12, 8, null), Node(0, 7, 2), Node(null, 0, 10), Node(11, 3, 0), Node(null, 99, null), Node(7, 1, 1), Node(null, 2, 8), Node(3, 5, 5)),
9,
listOf(99)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
18,
listOf(80, 80, 67, 71)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
8,
listOf(1, -1, 1, -1, 1, -1, 1)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
4,
listOf(1, 3, 6, 10, 15, 21)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
14,
listOf(3, 1, 4, 1, 5, 9, 2, 6, 5, 3)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
17,
listOf(8, 6, 7, 5, 3, 0, 9)
),
Test(
listOf(Node(4, 11, 0), Node(null, 22, 3), Node(null, 33, 3), Node(1, 44, 4), Node(3, 55, null), Node(7, 66, 7), Node(6, 77, 6)),
3,
listOf(22, 44, 55)
),
Test(
listOf(Node(null, -123, null)),
0,
listOf(-123)
)
)

var f:(List<List<Int?>>,Int)-> Sequence<Int?> =
{g,S->generateSequence(generateSequence(S){g[it][0]}.last()){g[it][2]}.map{g[it][1]}}

fun main(args: Array<String>) {
    for ((input, start, result) in TEST) {
        val out = f(input.map { it.toList() }, start).toList()
        if (out != result) {
            throw AssertionError("$input $start $result $out")
        }
    }
}

蒂奥

在线试用


我只希望generateSequence短一些
jrtapsell

0

JavaScript的ES6,70个 63字节

(x,i,a)=>(h=_=>i&&h(a(x[i].v),i=x[i].n))(x.map(_=>i=x[i].p||i))

测试用例:

F([undefined,{p:0,v:12,n:2},{p:1,v:99,n:3},{p:2,v:37,n:0}],1,alert)

alert需求是在你的函数的主体,对你的总字节数。
粗野的


+10 / -9并非共识。
毛茸茸的

我看不到确切的+和-s。另外,这是javascript的预期输出方式,也是输出延迟时的唯一方式
l4m2,18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.