Entiendo cómo se usan típicamente los árboles para modificar las estructuras de datos persistentes (crear un nuevo nodo y reemplazar todos sus antecesores).Modificación de masa eficiente de estructuras de datos persistentes
Pero, ¿y si tengo un árbol de 10.000 nodos y tengo que modificar 1000 de ellos? No quiero ir y crear miles de nuevas raíces, solo necesito la raíz nueva que resulta de modificar todo a la vez.
Por ejemplo: Tomemos un árbol binario persistente, por ejemplo. En el caso del nodo de actualización única, realiza una búsqueda hasta que encuentra el nodo, crea uno nuevo con las modificaciones y los elementos secundarios anteriores, y crea antepasados nuevos hasta la raíz.
En el caso de la actualización masiva podríamos hacer: En lugar de simplemente actualizar un solo nodo, va a actualizar 1000 nodos en una sola pasada.
En el nodo raíz, la lista actual es la lista completa. Luego divide esa lista entre los que coinciden con el nodo izquierdo y los que coinciden con el derecho. Si ninguno coincide con uno de los niños, no descienda a él. A continuación, desciende al nodo izquierdo (suponiendo que haya coincidencias), divide su lista de búsqueda entre sus elementos secundarios y continúa. Cuando tiene un solo nodo y una coincidencia, lo actualiza y vuelve a subir, reemplazando y actualizando ancestros y otras ramas, según corresponda.
Esto daría como resultado una sola raíz nueva aunque modificó cualquier cantidad de nodos.
Gracias por la gran información. No estaba considerando caminar sobre toda la estructura. Agregué un ejemplo en la pregunta. Me parece que este ejemplo tendría una huella de memoria mucho más pequeña que el enfoque de 1 por 1. Al dividir la lista en cada rama, podría ser similar a O (k log n) para la búsqueda, pero cada nodo que se actualiza (incluidos los nodos antecesores) se actualiza solo una vez. 1 por 1 caso: (k log n) para buscar cada nodo, pero luego otro (k * promedio de profundidad) para actualizar antepasados (algunos repetidamente). En el ejemplo de la pregunta, ¿no se reduciría eso significativamente? – mentics
Claro, su nuevo ejemplo de árbol binario es esencialmente lo que me refería como caminar por toda la estructura, porque en general hará llamadas recursivas en ambos lados del árbol. Por supuesto, en casos especiales, es posible que puedas parar temprano y evitar atravesar partes del árbol. En otros casos, es posible que deba recorrer parte del árbol solo para descubrir que no sucedieron cambios realmente en esa parte del árbol. Ahí es cuando el valor de retorno booleano adicional que mencioné podría ser útil si desea evitar una asignación innecesaria. –
Solo camina por una rama si hay nodos que actualizar que coincidan con esa rama. Busca de la misma manera que el caso 1 por 1, pero realiza todas las k búsquedas al mismo tiempo. Por lo tanto, nunca tendrá que devolver un booleano sobre si se actualizó o no porque no habría bajado de esa rama para comenzar a menos que se actualice. – mentics