En informática , un árbol k -d (abreviatura de árbol k-dimensional ) es una estructura de datos de partición espacial para organizar puntos en un espacio k -dimensional . K-dimensional es aquello que concierne exactamente a k ejes ortogonales o a un espacio de cualquier número de dimensiones . [1] Los árboles k -d son una estructura de datos útil para varias aplicaciones, tales como:
Los árboles k -d son un caso especial de árboles de partición de espacio binario .
El árbol k -d es un árbol binario en el que cada nodo es un punto k -dimensional. [2] Se puede pensar que cada nodo que no es hoja genera implícitamente un hiperplano de división que divide el espacio en dos partes, conocidas como semiespacios . Los puntos a la izquierda de este hiperplano están representados por el subárbol izquierdo de ese nodo y los puntos a la derecha del hiperplano están representados por el subárbol derecho. La dirección del hiperplano se elige de la siguiente manera: cada nodo del árbol está asociado con una de las k dimensiones, con el hiperplano perpendicular al eje de esa dimensión. Entonces, por ejemplo, si para una división particular se elige el eje "x", todos los puntos en el subárbol con un valor "x" menor que el nodo aparecerán en el subárbol izquierdo y todos los puntos con un valor "x" mayor aparecerán en el subárbol izquierdo. estar en el subárbol derecho. En tal caso, el hiperplano estaría determinado por el valor x del punto, y su normal sería el eje x unitario. [3]
Dado que hay muchas formas posibles de elegir planos de división alineados con los ejes, existen muchas formas diferentes de construir árboles k -d. El método canónico de construcción de árboles k -d tiene las siguientes restricciones: [4]
Este método conduce a un árbol k -d equilibrado , en el que cada nodo de hoja está aproximadamente a la misma distancia de la raíz. Sin embargo, los árboles equilibrados no son necesariamente óptimos para todas las aplicaciones.
Tenga en cuenta que no es necesario seleccionar el punto medio. En el caso de que no se seleccionen los puntos medianos, no hay garantía de que el árbol esté equilibrado. Para evitar codificar un algoritmo complejo de búsqueda de la mediana [5] [6] o usar una clasificación como heapsort o mergesort para ordenar los n puntos, una práctica popular es ordenar un número fijo de puntos seleccionados aleatoriamente y usar la mediana de esos puntos para servir como plano de división. En la práctica, esta técnica suele dar como resultado árboles muy equilibrados.
Dada una lista de n puntos, el siguiente algoritmo utiliza una clasificación de búsqueda de mediana para construir un árbol k -d equilibrado que contenga esos puntos.
función kdtree ( lista de puntos pointList, int profundidad){ // Seleccione el eje según la profundidad para que el eje recorra todos los valores válidos var int axis := profundidad mod k; // Ordena la lista de puntos y elige la mediana como elemento pivote selecciona la mediana por eje de pointList; // Crea un nodo y construye un subárbol nodo.ubicación: = mediana; node.leftChild := kdtree(puntos en pointList antes de la mediana, profundidad+1); node.rightChild := kdtree(puntos en pointList después de la mediana, profundidad+1); nodo de retorno ;}
Es común que los puntos "después" de la mediana incluyan sólo aquellos que son estrictamente mayores que la mediana en la dimensión actual. Para los puntos que se encuentran en la mediana en la dimensión actual, es posible definir una función que los compare en todas las dimensiones. En algunos casos, es aceptable dejar que los puntos iguales a la mediana se encuentren en un lado de la mediana, por ejemplo, dividiendo los puntos en un subconjunto "menor que" y un subconjunto "mayor o igual que".
Este algoritmo crea la invariante de que para cualquier nodo, todos los nodos del subárbol izquierdo están en un lado de un plano de división y todos los nodos del subárbol derecho están en el otro lado. Los puntos que se encuentran en el plano de división pueden aparecer a ambos lados. El plano de división de un nodo pasa por el punto asociado con ese nodo (al que se hace referencia en el código como nodo.ubicación ).
Algoritmos alternativos para construir un árbol k -d equilibrado preclasificar los datos antes de construir el árbol. Luego, mantienen el orden de la clasificación previa durante la construcción del árbol y, por lo tanto, eliminan el costoso paso de encontrar la mediana en cada nivel de subdivisión. Dos de estos algoritmos construyen un árbol k -d equilibrado para ordenar triángulos con el fin de mejorar el tiempo de ejecución del trazado de rayos para gráficos por computadora tridimensionales . Estos algoritmos ordenan previamente n triángulos antes de construir el árbol k -d y luego construyen el árbol a tiempo en el mejor de los casos. [7] [8] Un algoritmo que construye un árbol k -d equilibrado para ordenar puntos tiene una complejidad en el peor de los casos de . [9] [10] Este algoritmo preclasifica n puntos en cada una de las k dimensiones utilizando una clasificación como Heapsort o Mergesort antes de construir el árbol. Luego mantiene el orden de estos k preordenamientos durante la construcción del árbol y, por lo tanto, evita encontrar la mediana en cada nivel de subdivisión.
Se agrega un nuevo punto a un árbol k -d de la misma manera que se agrega un elemento a cualquier otro árbol de búsqueda . Primero, recorra el árbol, comenzando desde la raíz y moviéndose hacia el hijo izquierdo o derecho dependiendo de si el punto a insertar está en el lado "izquierdo" o "derecho" del plano de división. Una vez que llegue al nodo bajo el cual debe ubicarse el hijo, agregue el nuevo punto como hijo izquierdo o derecho del nodo hoja, nuevamente dependiendo de qué lado del plano de división del nodo contiene el nuevo nodo.
Agregar puntos de esta manera puede hacer que el árbol se desequilibre, lo que provocará una disminución del rendimiento del mismo. La tasa de degradación del rendimiento del árbol depende de la distribución espacial de los puntos del árbol que se agregan y del número de puntos agregados en relación con el tamaño del árbol. Si un árbol se desequilibra demasiado, es posible que sea necesario volver a equilibrarlo para restaurar el rendimiento de las consultas que dependen del equilibrio del árbol, como la búsqueda del vecino más cercano.
Para eliminar un punto de un árbol k -d existente sin romper el invariante, la forma más sencilla es formar el conjunto de todos los nodos y hojas de los hijos del nodo objetivo y recrear esa parte del árbol. [11]
Otro enfoque es encontrar un reemplazo para el punto eliminado. [12] Primero, busque el nodo que contiene el punto que se va a eliminar. Para el caso base, donde R es un nodo hoja, no se requiere reemplazo. Para el caso general, busque un punto de reemplazo, digamos , del subárbol con raíz en . Reemplace el punto almacenado en con . Luego, elimine recursivamente .
Para encontrar un punto de reemplazo, si discrimina (digamos) y tiene un hijo correcto, encuentre el punto con el valor mínimo del subárbol con raíz en el hijo correcto. De lo contrario, busque el punto con el valor máximo del subárbol con raíz en el hijo izquierdo.
Equilibrar un árbol k -d requiere cuidado porque los árboles k -d se clasifican en múltiples dimensiones, por lo que la técnica de rotación de árboles no se puede utilizar para equilibrarlos, ya que esto puede romper la invariante.
Existen varias variantes de árboles k -d equilibrados. Incluyen árbol k -d dividido, pseudo árbol k -d, árbol KDB , árbol hB y árbol Bkd . Muchas de estas variantes son árboles kd adaptativos .
El algoritmo de búsqueda de vecino más cercano (NN) tiene como objetivo encontrar el punto en el árbol más cercano a un punto de entrada determinado. Esta búsqueda se puede realizar de manera eficiente utilizando las propiedades del árbol para eliminar rápidamente grandes porciones del espacio de búsqueda.
La búsqueda de un vecino más cercano en un árbol k -d se realiza de la siguiente manera:
Generalmente, el algoritmo utiliza distancias al cuadrado para comparar y evitar calcular raíces cuadradas. Además, puede ahorrar cálculos al mantener la mejor distancia actual al cuadrado en una variable para comparar.
El algoritmo se puede ampliar de varias maneras mediante modificaciones simples. Puede proporcionar los k vecinos más cercanos a un punto manteniendo k mejores actuales en lugar de solo uno. Una rama sólo se elimina cuando se han encontrado k puntos y la rama no puede tener puntos más cerca que cualquiera de los k mejores actuales.
También se puede convertir en un algoritmo de aproximación para ejecutarlo más rápido. Por ejemplo, la búsqueda aproximada del vecino más cercano se puede lograr simplemente estableciendo un límite superior en el número de puntos a examinar en el árbol o interrumpiendo el proceso de búsqueda basándose en un reloj de tiempo real (que puede ser más apropiado en implementaciones de hardware). El vecino más cercano para los puntos que ya están en el árbol se puede lograr no actualizando el refinamiento para los nodos que dan una distancia cero. Como resultado, esto tiene la desventaja de descartar puntos que no son únicos pero que están ubicados junto al punto de búsqueda original.
El vecino más cercano aproximado es útil en aplicaciones en tiempo real como la robótica debido al importante aumento de velocidad que se obtiene al no buscar exhaustivamente el mejor punto. Una de sus implementaciones es la búsqueda best-bin-first .
Una búsqueda de rango busca rangos de parámetros. Por ejemplo, si un árbol almacena valores correspondientes a ingresos y edad, entonces una búsqueda de rango podría ser algo así como buscar todos los miembros del árbol que tengan una edad entre 20 y 50 años y un ingreso entre 50.000 y 80.000. Dado que los árboles kd dividen el rango de un dominio a la mitad en cada nivel del árbol, son útiles para realizar búsquedas de rango.
Los análisis de árboles de búsqueda binarios han encontrado que el peor momento para la búsqueda de rango en un árbol k -dimensional k -d que contiene n nodos viene dado por la siguiente ecuación. [13]
Encontrar el punto más cercano es una operación promedio, en el caso de puntos distribuidos aleatoriamente, aunque el análisis en general es complicado. [14]
En espacios de alta dimensión, la maldición de la dimensionalidad hace que el algoritmo necesite visitar muchas más ramas que en espacios de menor dimensión. En particular, cuando el número de puntos es sólo ligeramente mayor que el número de dimensiones, el algoritmo es sólo ligeramente mejor que una búsqueda lineal de todos los puntos. Como regla general, si la dimensionalidad es k , el número de puntos en los datos, n , debe ser . De lo contrario, cuando se utilizan árboles k -d con datos de alta dimensión, la mayoría de los puntos del árbol se evaluarán y la eficiencia no es mejor que la búsqueda exhaustiva [15] y, si se requiere una respuesta lo suficientemente buena y rápida, En su lugar, se deben utilizar métodos aproximados del vecino más cercano.
Además, incluso en un espacio de baja dimensión, si la distancia promedio por pares entre los k vecinos más cercanos del punto de consulta es significativamente menor que la distancia promedio entre el punto de consulta y cada uno de los k vecinos más cercanos, el rendimiento de la búsqueda del vecino más cercano se degrada hacia lineal, ya que las distancias desde el punto de consulta a cada vecino más cercano son de magnitud similar. (En el peor de los casos, considere una nube de puntos distribuidos en la superficie de una esfera centrada en el origen. Cada punto es equidistante del origen, por lo que la búsqueda del vecino más cercano al origen tendría que recorrer todos los puntos del origen. superficie de la esfera para identificar al vecino más cercano, que en este caso ni siquiera es único).
Para mitigar la degradación potencialmente significativa del rendimiento de una búsqueda de árbol k -d en el peor de los casos, se puede proporcionar un parámetro de distancia máxima al algoritmo de búsqueda de árbol y la búsqueda recursiva se puede podar siempre que se encuentre el punto más cercano en una rama determinada del árbol. no puede estar más cerca que esta distancia máxima. Esto puede provocar que una búsqueda de vecino más cercano no devuelva un vecino más cercano, lo que significa que no hay puntos dentro de esta distancia máxima desde el punto de consulta.
En lugar de puntos, un árbol k -d también puede contener rectángulos o hiperrectángulos . [16] [17] Por lo tanto, la búsqueda de rango se convierte en el problema de devolver todos los rectángulos que cruzan el rectángulo de búsqueda. El árbol se construye de la forma habitual con todos los rectángulos en las hojas. En una búsqueda de rango ortogonal , se utiliza la coordenada opuesta cuando se compara con la mediana. Por ejemplo, si el nivel actual se divide a lo largo de x alto , verificamos la coordenada x bajo del rectángulo de búsqueda. Si la mediana es menor que la coordenada x baja del rectángulo de búsqueda, entonces ningún rectángulo en la rama izquierda podrá cruzarse con el rectángulo de búsqueda y, por lo tanto, podrá podarse. De lo contrario, se deben atravesar ambas ramas. Véase también árbol de intervalos , que es un caso especial unidimensional.
También es posible definir un árbol k -d con puntos almacenados únicamente en las hojas. [4] Esta forma de árbol k -d permite una variedad de mecanismos de división distintos de la división mediana estándar. La regla de división del punto medio [18] selecciona en la mitad del eje más largo del espacio que se busca, independientemente de la distribución de puntos. Esto garantiza que la relación de aspecto será como máximo 2:1, pero la profundidad depende de la distribución de puntos. Una variación, llamada punto medio deslizante, solo se divide por la mitad si hay puntos en ambos lados de la división. De lo contrario, se divide en el punto más cercano al centro. Maneewongvatana y Mount muestran que esto ofrece un rendimiento "suficientemente bueno" en conjuntos de datos comunes.
Usando el punto medio deslizante, se puede responder una consulta aproximada del vecino más cercano en formato . Con este método se puede responder al conteo de rango aproximado .
Variaciones cercanas:
Variaciones relacionadas:
Problemas que se pueden abordar con árboles k -d: