¿Qué estructuras de datos recomendaría que representen una colección de subconjuntos de y admitan las siguientes operaciones?
- : inserta S en la colección.
- : devuelve verdadero si existe S ′ en la colección tal que S ′ ⊂ S , falso en caso contrario.
Mi criterio principal sería la eficiencia práctica del tiempo.
ds.data-structures
Caleb Poucher
fuente
fuente
Respuestas:
Su problema me parece mucho a la recuperación de información (IR). Allí tiene una colección de conjuntos de palabras (también conocidos como documentos) y desea encontrar no solo la existencia, sino todos los conjuntos / documentos que satisfacen la condición de consulta.
Dado que los elementos establecidos son números, puede aprovechar la estructura aparente, por lo que un índice de firma sería de gran utilidad.
Recomendaría echar un vistazo a los documentos IR, especialmente relacionados con las estructuras del diccionario, como los árboles, pero tenga en cuenta que el espacio suele ser un problema para esos sistemas, mientras que podría no ser un problema para su caso.
fuente
Podrías usar un árbol de búsqueda. No es "estándar", como se usa para los universos ordenados (números reales, cadenas ...) sino un tipo más general, como los insinuados por el proyecto GiST . Hay árboles de búsqueda para consultas espaciales, así como las basadas en axiomas métricos , para indexar espacios métricos (distancia). La idea general (de la cual el enfoque orientado a intervalos "menor que / mayor que" de los árboles de búsqueda ordenados ordinarios es una especialización) es descomponer el conjunto de datos en subconjuntos, generalmente jerárquicamente. Esta jerarquía de subconjuntos está (obviamente) representada por un árbol, donde los hijos de cada nodo representan subconjuntos, y cada nodo tiene alguna forma de predicado., que le permite verificar si existe una superposición entre el conjunto (conceptual) de objetos relevantes para su consulta y los que se encuentran en ese subárbol (es decir, subconjunto).
Por ejemplo, para un árbol espacial en el plano euclidiano, cada objeto podría ser un punto, y los predicados podrían ser rectángulos delimitadores , que contienen todos los puntos encontrados en ese nodo o debajo de él. Si una consulta es un rectángulo (y desea encontrar todos los puntos en ese rectángulo), puede eliminar recursivamente los subárboles cuyos rectángulos delimitadores no se superponen con su consulta.
En su caso, podría construir un árbol donde cada nodo contenga una estructura de conjunto que le permita detectar si su consulta es un subconjunto. Si no, ese subárbol completo puede eliminarse, ya que su consulta nunca podría ser un subconjunto de ninguno de los nodos secundarios (y ciertamente no las hojas, que probablemente representarían los datos verdaderos).
A diferencia de los árboles de búsqueda ordinarios, aquí no hay una garantía de tiempo de búsqueda en general: probablemente visitará varias ramas, por lo que incluso si tiene un árbol perfectamente equilibrado, probablemente tendrá un tiempo de ejecución superlogarítmico. Este es un enfoque más heurístico, pero podría ser efectivo aún.
Lo que necesita, para construir este árbol, sería alguna forma de método de agrupamiento jerárquico que se ajuste a sus datos. El proyecto GiST en realidad tiene un árbol muy parecido a lo que necesita, con una implementación en C (aunque verifica si la consulta se superpone, no si es un subconjunto; debería ser fácil de modificar). Sin embargo, el árbol equilibrado estilo Gi-Tree basado en disco de GiST podría ser excesivo. Probablemente solo desee agrupar conjuntos similares, jerárquicamente, y podría hacerlo utilizando cualquier algoritmo de agrupación estándar, utilizando algo como la distancia de Hamming (o algo más elegante). Cuanto más parecidos sean los nodos hermanos, "más estricto" será el predicado delimitador del padre (es decir, el conjunto que representa su unión) y, por lo tanto, más eficiente será su búsqueda.
En resumen, mi sugerencia es:
Si necesita que el árbol sea dinámico, también hay muchas formas de hacerlo. Por ejemplo, podría atravesar recursivamente el árbol, encontrar la ubicación que mejor se adapte (pasando por los nodos con la mayor superposición / distancia de Hamming más pequeña), actualizando las uniones (predicados delimitadores) a medida que avanza. Las eliminaciones son un poco más difíciles, tal vez; simplemente puede marcar los objetos que faltan y luego reconstruir los subárboles (o la estructura completa) cuando el número de objetos marcados alcanza un cierto umbral.
Si esto funciona bien para su aplicación podría ser difícil de decir a priori, pero debería ser fácil de verificar experimentalmente. Además, hay mucho espacio para ajustar.
fuente