C++Builder make Dictionary

2 отговора 72 прегледа
#1

C++Builder make Dictionary

Може ли някой да ми каже по принцип как се организират данните в един речник да речем като SA Dictionary 97, за да се заеме по малко памет но така , че речника да работи бързо?
Имам в предвид:
1. организацията на данните(думите) във файла с думите.
2. четене на данните от файла при старт на речника и запис в някаква структура напр. свързан списък, балансирано дърво или др. от където после се търсят, четат и визуализират.
Въобще не знам дали съм на прав път.Ако някой е правил речник или знае как става нека даде идея.Като среда за разработка използвам Borland C++Builder 5
.

Отговор
в отговор на ist #2

Re: C++Builder make Dictionary

Всъщност SA Dictionary май не използва добра структура от данни. Прави превод от 100/думи в секунда на 400MHz Celeron. Иначе има няколко начина.
1. Тъй като се четат от файл те могат да бъдат предварително сортирани. Можем да извършим двоично търсене.
2. Можем да използваме хеш таблица.
3. Можем да използваме специална структура наречена Tries. Ако не намериш информация за tries мога да ти обясня по-подробно. Ето ти пример писан от мен:

/*
Spell Checker
Copyright (c) 2001 by Boris Yankov
[линк]
*/

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

const char endletter = '#';
const char dummyletter = '@';

struct dct {
char letter;
dct *nextw, *nextl;
};

class dict {
dct *ddata;
public:
dict();
~dict();
void add(const string& word);
bool isthere(const string& word) const;
bool remove(const string& word);
};

dict::dict()
{
ddata = new dct;
ddata->letter = dummyletter;
ddata->nextw = ddata->nextl = NULL;
}

dict::~dict()
{
// Free the memory there
}

void dict::add(const string& word)
{
dct *lvl = ddata;
string wrd = word + endletter;
int wl = wrd.size();
for (int pz = 0; pz < wl; pz++) {
dct *cpos = lvl;
dct *prev;

// Find letter pos
while (cpos && cpos->letter < wrd[pz] && cpos->letter != dummyletter)

{
prev = cpos;
cpos = cpos->nextl;
}

// Add letter if it not persist else just go to next level
if (cpos && cpos->letter == wrd[pz]) {
lvl = cpos->nextw;
continue;
}
if (cpos && cpos->letter == dummyletter) {
cpos->letter = wrd[pz];
}
if (!cpos || cpos->letter != wrd[pz]) {
dct *newl = new dct;
newl->letter = wrd[pz];
newl->nextw = NULL;
if (cpos) {
newl->nextl = cpos->nextl;
cpos->nextl = newl;
}
else {
prev->nextl = newl;
newl->nextl = NULL;
}
cpos = newl;
}
// Create dummy letter
lvl = new dct;
lvl->letter = dummyletter;
lvl->nextw = lvl->nextl = NULL;
cpos->nextw = lvl;
}
}

bool dict::isthere(const string& word) const
{
string wrd = word + endletter;
int wl = wrd.size();
dct *lvl = ddata;
for (int a = 0; a < wl; a++) {
dct *cpos = lvl;
while (cpos && cpos->letter < wrd[a])
cpos = cpos->nextl;
if (!cpos || cpos->letter != wrd[a])
return false;
lvl = cpos->nextw;
}
return true;
}

bool dict::remove(const string& word)
{
return true;
}

void main()
{
dict d;
ifstream fin("\\words");
cout << "Adding words to dictionary..." << endl;
string w;
int wcount = 0;
while (fin) {
fin >> w;
d.add(w);
wcount++;
}
fin.close();
cout << "Finished! Added " << wcount << " words." << endl;

string input;
do {
cin >> input;
if (!d.isthere(input))
cout << input << endl;
}
while (input != "#@#");
}

Отговор
в отговор на Eradicator #3

Re: C++Builder make Dictionary

Благодаря.
Ще прегледам кода и ще се обадя ако имам въпроси.
Бъди жив и здрав и дано има повече хора като теб.
Благодаря ти. ist.


Отговор