2011-06-17 5 views
6

Tengo una situación, como sigue:Algoritmo para obtener rápidamente una ordenación parcial a través de múltiples listas enlazadas

  • I tienen n listas enlazadas doblemente
  • Cada lista ha de comenzar un centinela y terminar
  • las listas tienen todos la misma principio y nodo final (no es necesario, pero por motivos de simplicidad)
  • las listas son homogéneas y pueden compartir elementos

me gustaría encontrar una ordenación parcial de todos los nodos en todas las n listas, comenzando con el nodo comenzando y terminando con, así, el nodo de extremo, de tal manera que cualquier nodo que aparece en nx listas , donde x < n, se ordenarán con respecto a los otros nodos en todas las listas en las que aparece.

Utilización de matrices para proporcionar un conjunto de ejemplo de listas:

first = [a, b, d, f, h, i]; 
second = [a, b, c,  f, g, i]; 
third = [a,   e, f, g, h, i]; 

Obviamente, una respuesta posible sería [a, b, c, d, e, f, g, h, i], pero otro el orden admisible sería [a, b, d, e, c, f, g, h, i].

Sé que hay es un algoritmo rápido para hacer esto, ¿alguien recuerda cómo funciona o cómo se llama? Ya tengo algunas versiones lentas, pero estoy seguro de que en algún lugar de Knuth hay uno mucho más rápido.

(. Y, antes de preguntar, esto no es para la tarea o proyecto Euler, y no puedo hacer esto más concreto Este es el problema.)

Editar: Estoy relativamente seguro de que el parcial el orden se define solo mientras los puntos finales estén en todas las listas y en las mismas posiciones (comienzo y final). No me opondría a una búsqueda en tiempo lineal para encontrar esos puntos finales, y si no se pueden encontrar, entonces se podría generar un error allí.

+2

¿Cuál sería la respuesta (s) si las listas tuvieran órdenes contradictorias, p. 'first = [a, b]' y 'second = [b, a]'? – antinome

+0

antinome: como se menciona en la edición anterior, prefiero generar un error antes de tiempo si no hay forma de obtener puntos finales válidos. – Corbin

Respuesta

2

Parece muy similar a Topological sort para mí. Hay varios algoritmos para obtener un estado ordenado topológicamente. El que particularmente me gusta es similar a una primera búsqueda de amplitud. Mantenga dos listas, uno de todos los nodos que no tienen bordes internos, digamos L (inicialmente solo el nodo a), y el otro con los nodos ordenados parcialmente, F.Ahora bien, en cada paso,

pick a node from `L`, 
do some operations (explained later), 
and move the chosen node to the `F` list. 

En el "paso de hacer algunas operaciones",

choose all successors of the source node which have exactly one in-link add them to L. 
Remove the link from the source node to all the successors in the previous step 

Ahora, la lista F tiene todos sus nodos topológicamente ordenados. Lamento la espantosa explicación, el enlace del wiki tiene buenos diagramas :)

+0

Incluso hay una sección sobre la relación con pedidos parciales. Me gusta mucho esta idea y puedo ver la elegancia en ella. El problema, entonces, sería una transformación eficiente de las múltiples listas vinculadas (¡que no están vinculadas de forma múltiple!) A un DAG. Ideas? – Corbin

+0

Entonces, ¿el objeto 'a' en la primera lista no es el mismo objeto' a' en la segunda lista? Yo no sigo Si ese es el caso, use una tabla hash (o cualquier estructura similar) para asignar cada objeto a un número común. Luego construye el DAG. Por ejemplo 'a' = 1,' b' = 2 etc. etc. Ahora, construye tu DAG usando el 1s y 2s en vez de 'a's y' b's – kyun

+0

@MostAwesomeDude: No entiendo tu pregunta: cualquier cosa aplicable a un DAG seguramente debe ser aplicable a algo que es más que un DAG (más en el sentido de que los bordes van en ambas direcciones). Si está atascado en cómo convertir sus listas a un gráfico, ha hecho una suposición ideal para ese problema: todos los primeros nodos en cada lista son iguales. Por lo tanto, esa es la raíz ideal de su gráfico, y cada lista representa una rama – JBSnorro

0

O estoy malentendido, o el algoritmo de alienhard puede fallar. (Me gustaría añadir esto como un comentario, pero soy demasiado nuevo aquí para comentar.)

Considere este ejemplo:

first = [a, b, c, d,    i]; 
second = [a,  d, e, f,  i]; 
third = [a,    f, g, h, i]; 

algoritmo de Alienhard dará: a=0, b=1, c=2, d=3, e=2, f=3, g=2, h=3, i=4.

El algoritmo requiere que e sea anterior a d aunque e siga d en segundo.

+0

Sí, gracias, tienes razón. También pensé que hay casos triviales donde esto falla. Hubiera sido demasiado bueno si funcionó tan simple y rápido;). He marcado mi respuesta para eliminarla. – alienhard

+0

Tiene razón. – Corbin

Cuestiones relacionadas