Chiedendo il modo più efficiente per fare un albero binario di ricerca in un correttore ortografico con la lettura nel dire file di dizionario di 1000 parole e poi averlo controllare un altro documento che dire ha un paio di paragrafi.
Utilizzando un albero binario di ricerca come un correttore ortografico
un albero ternario trie sarebbe più efficiente
Se avete bisogno di fare un auto suggeriscono di ricerca / prefisso bene, poi un albero albero patricia o radix vale la pena guardare.
Con l'esempio che hai dato, le prestazioni è probabile che sia irrilevante, dal momento che su un PC tutta l'operazione richiede circa l'1% del tempo necessario all'utente di leggere il primo risultato si mostra, a condizione che non si utilizza un algoritmo completamente stupido . Ma ancora, darò per scontato che il problema è abbastanza grande che le prestazioni è un problema.
Se il file dizionario è preordinato in (come la maggior parte sono), e se il testo è piccolo rispetto al dizionario come lei, allora sarei fortemente tentato di ordinare il testo, forse rimuovendo i duplicati, e poi scorrere entrambe le liste side-by -side utilizzando la stessa procedura come un merge sort, ad eccezione di segnalare se ogni parola del testo è presente nel dizionario, invece di emettere un elenco unito.
Questo fa il lavoro in circa M registro M confronti per l'ordinamento, oltre alla maggior parte dei confronti N + M per l'iterazione, (forse meno, ma non la complessità-meno). Questo è abbastanza vicino alla complessità ottimale per un'operazione una tantum: per sbarazzarsi del termine lineare in N è necessario trovare il modo di non leggere l'intero dizionario da disco a tutti. Sono abbastanza sicuro che sia possibile bsearch nel file, tanto più che le parole sono piuttosto brevi, ma per i piccoli N E 'ancora da vedere se alla ricerca del posto sarà effettivamente più veloce di accesso seriale dei dati.
Essa ha le seguenti caratteristiche:
- Non è necessario per tenere il dizionario in memoria, solo il testo.
- Tuttavia, si fa solo un passaggio sopra il file dizionario.
- Non si fa alcuna elaborazione costosa del dizionario.
Naturalmente se il file dizionario non è pre-assortiti allora questo non funziona, e se è possibile mantenere il dizionario in giro in memoria per la successiva operazione di controllo ortografico allora si può ammortizzare il costo di I / O e di trasformazione in un albero in diversi testi diversi, che sarà una vittoria nel lungo periodo.
Se il dizionario è davvero enorme, allora si potrebbe beneficiare di archiviazione su disco in un modulo di pre-elaborati equivalente ad un albero sbilanciato ponderato secondo le frequenze relative dei diversi parole nella tua lingua. Poi si può fare a meno di O (N) l'accesso al disco per piccoli testi, e la maggior parte sistemi operativi si preoccupa di caricare in memoria a tutti, solo mmap il file e lasciare che la preoccupazione del sistema operativo su di esso. Per un dizionario di grandi dimensioni, l'intero cluster contenente parole che iniziano con "dimetil" non deve mai essere toccati.
Un'altra considerazione è un albero splay per il dizionario. Un albero di splay si sbilancia come si guarda le cose in esso, al fine di rendere i valori di uso frequente più veloce per trovare. La maggior parte di testo utilizza un piccolo numero di parole più volte, quindi se il testo è abbastanza lungo per giustificare l'overhead questo vincerà alla fine.
Entrambe le risposte sono soggette a punto di Steven A Lowe che per le stringhe, un trie batte un albero normale. Non so se si trova uno strombatura trie off-the-shelf, però.
Se stai solo cercando di vedere se una particolare parola esiste nel vostro dizionario (che è, è stato digitato correttamente), quindi non credo che un albero binario di ricerca è quello che stai cercando. Un modo migliore per memorizzare le informazioni sarebbe in uno stile albero dove ogni nodo successivo sul vostro albero è un carattere, e leggendo il percorso del nodo finale ti dà l'ortografia della parola. Faresti anche bisogno di aggiungere un marcatore per indicare una parola-finale.
Ad esempio: dire che il dizionario ha queste parole: auto, carrello, gatto, tazza, taglio
- C
- A
- R
- end
- T
- T
- end
- U
- P
- end
- T
- end
Controllare se esiste una parola è una questione di guardare ad ogni lettera singolarmente, e che esiste nei figli del nodo corrente.
Check for "cat"
Does "C" exist at the root level? Yes, move to the next letter.
Does "A" exist underneath C? Yes, move on.
Does "T" exist underneath A? Yes, move on.
Is there a word ending after the T? Yes. Word exists.
Check for "cu"
Does "C" exist at the root level? Yes, move to the next letter.
Does "U" exist at the root level? Yes, move to the next letter.
Is there a word ending after the U? No. Word does not exist.
Come si memorizzano queste informazioni dipende da voi. Come ha sottolineato Steven, un ternario Ricerca Trie potrebbe essere la strada da percorrere: ogni nodo avrebbe 27 possibili nodi figli.
Sei morto imposta sull'utilizzo di un albero binario di ricerca? Un filtro di Bloom sarebbe probabilmente una struttura dati più efficiente.
Visto che questa è una domanda compiti a casa ho intenzione di assumere che si deve utilizzare un albero pianura vecchio binario (senza alberi rosso-neri, alberi AVL, alberi Radix, ecc). La risposta è quindi di cercare di mantenere l'albero bilanciato come si costruisce dalla lista di parole. Un approccio è quello casuale la lista prima di leggere dentro, questo dà risultati ragionevoli. Ma è possibile ottenere risultati migliori se si ordina la sequenza di ingresso (usando lo stesso confronto come quello che usa l'albero), quindi in modo ricorsivo suddividere l'ingresso restituendo il punto centrale fino a quando non rimangono elementi. Il risultato è un albero bilanciato.
Ho bussato tre diversi modi di farlo in C #:
private static IEnumerable<T> BinaryTreeOrder<T>(IList<T> range, int first, int last)
{
if (first > last)
{
yield break;
}
int mid = (first + last) / 2;
yield return range[mid];
foreach (var item in BinaryTreeOrder(range, first, mid - 1))
{
yield return item;
}
foreach (var item in BinaryTreeOrder(range, mid + 1, last))
{
yield return item;
}
}
private static void BinaryTreeOrder<T>(IList<T> range, int first, int last,
ref IList<T> outList)
{
if (first > last)
{
return;
}
int mid = (first + last) / 2;
outList.Add(range[mid]);
BinaryTreeOrder(range, first, mid - 1, ref outList);
BinaryTreeOrder(range, mid + 1, last, ref outList);
}
private static void BinaryTreeOrder<T>(IList<T> range, int first, int last,
ref BinaryTree<T> tree) where T : IComparable<T>
{
if (first > last)
{
return;
}
int mid = (first + last) / 2;
tree.Add(range[mid]);
BinaryTreeOrder(range, first, mid - 1, ref tree);
BinaryTreeOrder(range, mid + 1, last, ref tree);
}
Questo sito dovrebbe aiutare che ha l'implementazione in Java.
Come suggerito un trie sarebbe più efficiente di un albero binario, ma è possibile utilizzare un HashMap e hash ogni parola. Si dispone di un piccolo dizionario (1000 voci). Come si attraversa il documento, verificare se le parole sono in HashMap. Se non lo sono, la parola si presume essere errata.
Questo non vi darà possibile correzione per una parola errata. E 'appena ti dice sì o no (corretta o meno).
Se si desidera che i suggerimenti ortografici per le parole errate si può iniziare dalla parola nel file, quindi generare tutte le parole 1 modifica distanza e aggiungere questi come figli della parola iniziale. In questo modo si stanno costruendo un grafico. Go 2 livelli di profondità per la massima velocità vs precisione. Se si genera un nodo parola che è nel dizionario, è possibile aggiungere a un elenco di possibili suggerimenti. Alla fine, riportare l'elenco dei possibili suggerimenti.
Per una migliore controllo ortografico, cercare anche di aggiungere in corrispondenza fonetica.
mare Yuh -> vedi Yah
Questo metodo (di creazione di grafici di stringhe 1 modifica di distanza) è "lento". Ma è un buon esercizio accademico. Runtime è O (n ^ filiali).
Se interessati qui è un link ad uno io ho costruito (per divertimento): https://github.com/eamocanu/spellcheck.graph
Alcuni grafici di esempio: https://github.com/eamocanu/spellcheck.graph/tree/master/graph%20photos
Ho anche aggiunto un componente di interfaccia utente ad esso che genera i grafici. Si tratta di una libreria esterna.













