Desenrede los datos doblemente vinculados


12

Una lista doblemente enlazada es una estructura de datos en la que cada nodo tiene un value"enlace" tanto con el previoussiguiente como nodesen el siguiente . Por ejemplo, considere los siguientes nodos con valores 12, 99 y 37:

Aquí, los nodos con valores 12 y 99 apuntan a sus respectivos nextnodos, con valores 99 y 37 . El nodo con el valor 37 no tiene nextpuntero porque es el último nodo de la lista. Del mismo modo, los nodos con valores 99 y 37 apuntan a sus respectivos previousnodos, 12 y 99 , pero 12 no tiene previouspuntero porque es el primer nodo de la lista.

La puesta en marcha

En la práctica, los "enlaces" de un nodo se implementan como punteros a las ubicaciones del nodo anterior y siguiente en la memoria. Para nuestros propósitos, la "memoria" será una matriz de nodos y la ubicación de un nodo será su índice en la matriz. Un nodo puede considerarse como una 3-tupla de la forma ( prev value next ). El ejemplo anterior, entonces, podría verse así:

Pero podría verse así, en cambio:

Comenzando en cualquier nodo, puede seguir los previousenlaces (que se muestran como los orígenes de las flechas rojas) para llegar a los nodos que lo preceden y los nextenlaces (flechas verdes) para encontrar los nodos posteriores para obtener todos los valores de los nodos en orden: [12, 99, 37].

El primer diagrama de arriba podría representarse en una matriz como [[null, 12, 1], [0, 99, 2], [1, 37, null]]. El segundo, entonces, sería [[2, 99, 1], [0, 37, null], [null, 12, 0]].

El reto

Escriba un programa que tome como entrada una matriz de nodos y el índice de un nodo y devuelva, en orden de lista, los valores de los nodos en la misma lista doblemente vinculada.

Una complicación

La "memoria" no siempre contendrá los nodos de una sola lista. Puede contener varias listas:

La matriz anterior contiene tres listas doblemente vinculadas, codificadas por colores para su conveniencia:

  1. Los nodos en los índices 7, 10, 1, 4, 3, 12(mostrando sólo los nextenlaces para reducir el desorden; haga clic para ampliar):

    Dada esta matriz y cualquiera de estos índices, su programa debería devolver, en orden, los valores [0, 1, 1, 2, 3, 5, 8].

  2. El nodo en el índice 9:

    Dado el índice 9, su programa debería regresar [99].

  3. Los nodos en índices 11, 8, 0, 6, 2:

    Dado uno de estos índices, debería volver [2, 3, 5, 7, 11].

Reglas

Entrada

Su programa recibirá como entrada:

  1. Una lista de 𝒏 nodos (3-tuplas como se describió anteriormente), donde 1 ≤ 𝒏 ≤ 1,000, en cualquier formato conveniente, por ejemplo, una matriz de matrices, una matriz "plana" de enteros con longitud 3𝒏, etc.

    Elementos Los 3-tuplas pueden estar en cualquier orden: ( prev value next ), ( next prev value ), etc. Para cada nodo, prevy nextserán null(u otro valor conveniente, por ejemplo -1), indicando el primer o último nodo en una lista doblemente enlazada, o un índice válido de la lista, ya sea basada en 0 o en 1 como sea conveniente. valueserá un entero de 32 bits con signo o el tipo entero más grande que admita su idioma, el que sea más pequeño.

  2. El índice 𝒑 de un nodo en la lista (1). El nodo indicado puede ser el primer nodo en una lista doblemente vinculada, el último nodo, un nodo intermedio o incluso el único nodo.

La lista de entrada (1) puede contener datos patológicos (p. Ej. Ciclos, nodos señalados por varios otros nodos, etc.), pero el índice de entrada (2) siempre apuntará a un nodo desde el que se puede obtener una salida bien formada. deducido

Salida

Su programa debería generar los valores de los nodos de la lista doblemente vinculada de la cual el nodo en el índice a es miembro, en orden de lista. La salida puede estar en cualquier formato conveniente, pero sus datos deben incluir solo los nodos value.

Victorioso

Este es el . La respuesta más corta en bytes gana. Se aplican lagunas estándar.

Casos de prueba

A continuación, cada caso de prueba tiene la forma:

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

... donde Xhay una letra para identificar el caso de prueba, la segunda línea es la lista de entrada, la tercera línea es el índice de entrada basado en 0 y la cuarta línea es la salida.

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



¿Se permite la entrada como tres matrices (una que contiene todos los nodos predecesores en orden, uno de valores y un nodo sucesor), o está muy lejos del concepto de tuplas?
Sanchises

@Sanchises Lo siento, demasiado lejos para mí.
Jordan

¡Está bien! Pensé que sí, pero quería adelantarme a cualquier comentario sobre mi respuesta que dijera que podía reducir dos bytes tomando matrices separadas.
Sanchises

Respuestas:


1

05AB1E , 25 bytes

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

Pruébalo en línea!

Explicación

è[¬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

Haskell , 79 65 59 55 bytes

-6 bytes gracias a Brute Force .

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

Define la función #que acepta una lista de listas de enteros, donde nullse representa como -1, y devuelve una lista de valores de nodo.

Pruébalo en línea!

Explicación

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

Defina la función !que itera a través de los nodos comenzando en el nodo iy devuelve una lista de índices visitados. Acepta el segundo argumento dque especifica qué índice de la "tupla" se usa como índice del siguiente nodo ( d==2iterar hacia adelante, d==0iterar hacia atrás).

(i!0)

Iterar hacia atrás a partir del índice dado y devolver los índices visitados.

last(i!0)

Tome el último índice visitado, que es el comienzo de la lista.

last(i!0)!2

Iterar desde el principio de la lista.

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

Reemplace cada índice visitado con el valor del nodo.


Casi podría escribir x!!i!!1como i!1!!1, pero se rompe debido -1a las salidas. Si solo elige otro valor centinela para representar null(digamos -9), funcionará, pero siempre se interrumpirá para alguna entrada, lo cual es bastante molesto.
Lynn

3

Python 2 , 60 bytes

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

Pruébalo en línea!

Esta es la respuesta de Chas Brown, menos estos campos de golf:

  • Reutilizo n, guardando una tarea
  • Guardo la última n válida en m, lo que me permite
  • coloque la impresión después de la tarea en la línea 3, guardándome la impresión final
  • Solo uso ~ n en lugar de - ~ n, porque los valores negativos son tan verdaderos como los positivos, lo que me ahorra 2 caracteres.


2

MATL , 39 bytes

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

Pruébalo en línea!

Casi un puerto directo de mi respuesta Octave, pero esta versión encuentra el final primero, y luego lo funciona al revés, en lugar de al revés, lo que ahorró un byte.

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 bytes

<?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);

Pruébalo en línea!

De entrada se toma como una cadena de consulta x[]=-1&x[]=1&x[]=1...(todos los nodos de una matriz plana), en el orden de next, prevy, a continuación valuepara cada nodo con -1 utilizado para poner fin a los nodos.


1

Python 2 , 81 77 bytes

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

Pruébalo en línea!

EDITAR: Thx al Sr. Xcoder por 4 bytes ...

Toma una lista de tuplas [u, v, w] donde u y w son -1 para representar el principio / final del segmento de la lista vinculada.


77 bytes ¡ Pruébelo en línea! . Los booleanos son subclases de int, por lo que solo 0es Falsy y, por u>=0lo tanto, se puede jugar golf u+1y esto se puede acortar aún más -~upara eliminar el espacio en blanco.
Sr. Xcoder

@Señor. Xcoder - Sí, ¡muy bien!
Chas Brown

1

Octava , 81 78 76 bytes

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

Pruébalo en línea!

Versión bastante sencilla. La explicación se deja como un ejercicio para el lector. A continuación se presenta una versión mucho más divertida :

Octava , 142 99 92 bytes

@(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)]

Pruébalo en línea!

Oye, escuché que te gustaban las funciones anónimas ...

Toma una nx3matriz, con la primera columna el predecesor, la segunda columna el valor y el tercer valor los nodos sucesores. Todos los índices de nodo están basados ​​en 1, que es el valor predeterminado en 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 bytes

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

Embellecido

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

Prueba

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")
        }
    }
}

TIO

TryItOnline


Solo deseo que generateSequence sea más corto
jrtapsell

0

JavaScript ES6, 70 63 Bytes

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

Caso de prueba:

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

La alertnecesidad de estar en el cuerpo principal de su función y contar para su total de bytes.
Shaggy


+10 / -9 no es un consenso.
Shaggy

No veo exactamente + y - s. Además, es la forma de salida prevista de javascript, y solo cuando la salida tiene algún retraso
l4m2
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.