2010-08-04 16 views
5

Soy un principiante de C++. ¿Puede alguien decirme la mejor estructura de datos en C++ para almacenar todas las palabras en un diccionario y encontrar si hay una palabra en el diccionario? Sé que las tablas hash son las mejores, pero no sé qué estructura de datos las usa.Mejor estructura de datos en C++ para encontrar una cadena en un diccionario

Muchas gracias de antemano.

+0

Existen archivos C++ DS proporcionados por la biblioteca estándar, como mapas, conjuntos, etc. Entonces, ¿cuál es el mejor DS para buscar una cadena? Leeré todas las cadenas y buscaré. – brett

Respuesta

9

La biblioteca estándar de su implementación en C++ puede tener unordered_set o hash_set. Ellos son esencialmente lo mismo; el primero es parte del próximo estándar C++ 0x y es compatible con algunos de los últimos compiladores, el último es del SGI STL original y se incluye en muchas implementaciones de bibliotecas estándar.

+1

¿Hash_set o unordered_set forman parte de la biblioteca estándar? – brett

+0

@brett: 'hash_set': ¿Oficialmente? No. Pero muchas implementaciones de bibliotecas estándar (incluyendo Visual C++ y libstdC++) lo incluyen. 'unordered_set': Todavía no. Será parte de la biblioteca estándar cuando se haya aprobado C++ 0x en algún momento de 2011. Algunas implementaciones de bibliotecas estándar (por ejemplo, la biblioteca de Visual C++ 2010) lo incluyen. –

+0

¿Puedo usarlo en mi compilador de Linux? G ++? Si no, ¿cuál es la mejor estructura de datos? – brett

2

hash_map, si lo tiene en la biblioteca del compilador de C++ (por ejemplo, GNU C++ o Microsoft Visual C++). Si está utilizando algún otro compilador menos extendido, sospecho que puede encontrar una implementación decente de terceros de hash_map de todos modos.

El próximo estándar de C++ llama a esta misma estructura de datos std::unordered_map.

Si no desea asociar ninguna información con palabras en su diccionario, simplemente registre si hay una palabra presente o no, puede usar las variaciones _set (en lugar de _map) de la estructura de datos anterior escribir nombres

Por supuesto, todas son plantillas (como todos los contenedores en la biblioteca estándar de C++), por lo que deberá crear instancias apropiadas con la sintaxis típica de la plantilla.

+0

Pero creo que mejorará con un conjunto de palabras, no con un mapa que sea un contenedor asociativo de valores-clave. Como dijo James, cualquier implementación del conjunto debería ser suficiente. –

+0

@ Hernán, como mencioné, si solo necesita la información de presencia/ausencia, 'hash_set' o' unordered_set' será suficiente; si alguna vez necesita registrar cualquier información auxiliar, entonces las variantes '..._ map' ser mejor (y tan eficiente). –

0

Si el único requisito es decidir si una palabra está contenida en un diccionario que nunca cambia, sin necesidad de otro tipo de información sobre la palabra (por ejemplo, un corrector ortográfico), entonces Bloom filter es un eficiente estructura de datos para esta tarea.

Si hay otros datos para asociar con cada palabra que debe buscarse, std::map es un buen punto de partida de propósito general.

Si se necesita autocompletar (cuando se ha ingresado una palabra parcial), se puede usar un Prefix tree (trie).

+0

Un Bloom Filter es una estructura de datos probabilísticos; no puede darte una respuesta definitiva de Sí/No. Los falsos positivos son posibles, pero los falsos negativos no lo son. Sin embargo, el trie es una buena idea. –

4

hashes son bastante buenos, pero la mejor estructura es trie. Puede obtener un trie de <ext/pb_ds/assoc_container.hpp> en GCC. Ver the online reference.

#include <ext/pb_ds/assoc_container.hpp> 
#include <string> 
#include <iostream> 

int main() { 
     pb_ds::trie< std::string, int > dict; 

     dict.insert(std::make_pair("hello", 3)); 

     std::cerr << (dict.find("hello") != dict.end()) << std::endl; 
     std::cerr << (dict.find("goodbye") != dict.end()) << std::endl; 
} 

Sólo map funcionalidad -como, no una pura set, se proporciona. En la muestra anterior agregué un dummy int como datos para mapear a ... realmente no debería doler mucho.

Lo que duele es que esto no funcionará fuera de GCC.

Por otro lado, una tabla hash -standard no (no std:: o ext:: nada) le permitiría sólo para encontrar coincidencias aproximadas, es decir, a buscar entre las sumas de comprobación de palabras en lugar de las palabras mismas. Esa sería la solución más rápida y compacta. Los diccionarios basados ​​en Bloom filters pueden contener muchos miles de palabras en algunos kilobytes.

+0

¿Cómo es que no funciona fuera de GCC? No hay forma de importar estas bibliotecas en Visual Studio (compilador CL)? –

+0

@YechielLabunskiy El archivo simplemente se incluye con GCC. Podría funcionar en MSVC si no depende de ninguna extensión de GCC o si activa cualquier error de MSVC. Sin duda vale la pena intentarlo. Sin embargo, tendría que tratarlo como una biblioteca independiente de terceros y controlarlo en busca de actualizaciones. – Potatoswatter

0

Si está dispuesto a rodar su propia solución y su diccionario es fijo, un perfect hash es un buen camino a seguir. Garantiza un tiempo de búsqueda constante.

+0

Tenía este problema exacto (diccionarios fijos generar) una o dos hace año y fue decepcionado al ver que prácticamente perfecta hash requiere una estructura de datos de dos niveles y la memoria, por tanto, múltiples lecturas por las operaciones de búsqueda. Termina siendo más lento que una tabla hash simple y llano con el encadenamiento. –

+0

Fwiw, aquí está el código terminé escribiendo para generar la tabla: http://hg.mozilla.org/tracemonkey/file/e555673c8119/js/src/xpconnect/src/qsgen.py#l1488 y para sondear: http : //hg.mozilla.org/tracemonkey/file/e555673c8119/js/src/xpconnect/src/xpcquickstubs.cpp#l70 en la práctica se genera un par de cadenas de 3 entradas de largo (unos búsquedas tienen que caminar las cadenas en absoluto sin embargo) . –

1

Yo preferiría usar un Trie. A Trie será una buena estructura de datos para construir un diccionario de memoria eficiente con búsquedas rápidas, y sí, autocompletado.

Piense en ello como una tabla hash, proporcionando una búsqueda rápida de pares clave-valor (o solo búsqueda de claves), pero a diferencia de una tabla hash, le permite iterar sobre las claves en orden ordenado.

Consulte Trie - Wiki para obtener más información/referencia.

Cuestiones relacionadas