一个应用二叉搜索树实现的字典,并存储结构于文件中
2003-02-13 10:01
627 查看
Super Power Dictionary[align=left][/align][align=left]
http://www3.sympatico.ca/qingzhehuang/SuperDictionary.htm
This is the third edition of my dictionary and it is very, very powerful now! Read in 20K words from a 2.3M text[/align][align=left]
file only uses less than 2seconds. However, ranking them will take 41seconds! As it need to track each node from[/align][align=left]
"WordTree" from "big to small" by "Frequency" and "rank" them by this sequence and then copy each node to a node[/align][align=left]
of "RankTree" then "insert" the new rankTree node into ranktree.[/align][align=left]
1。 Basic idea: I found out some mistakes in "ranking" functions. And it is really a hardtime to debug for a[/align][align=left]
whole day in lab(almost 8hours from 10:00AM to 18:30PM).[/align][align=left]
2。 Program design: The biggest problem is still how to walk round the "key" problem of RankTree by using "frequency"[/align][align=left]
as key to compare and at same keep all ancester class with their original functions.[/align][align=left]
3。 Major function:[/align][align=left]
A. void traverse(...);
I add one more parameters to let "RankTree Forest" to start traversing from its own "root".
B. void insertRank(Tree* node, void* userPtr)
This is a special "callback" function to construct "RankTree" forest by "traversing" each node of
"WordTree".
C. void Tree::maxWalk(...);
There are two format of this new MAXORDER way of traversing. Actually it is so-called "from big to small"
exactly opposite to "MIDORDER".
4。 Further improvement:
A. I have to go soon, so, no more time.
B. Still need improve.
C. Ranking counting and WordTree counting is differed by one, and I have not found the bug.
D. I hope I can rewrite the basic string-related part to enable the dictionary to read Chinese.[/align][align=left][/align]
#include <iostream> #include <cstdlib> #include <cstring> #include <fstream> #include <ctime>
using namespace std;
const char* DefaultBackup = "c://nickback.txt"; const MaxWordLength = 255;
enum TraverseOrder { PREORDER, MIDORDER, POSTORDER, MAXORDER };
class Tree { private: Tree* pLeft; Tree* pRight; Tree* pParent; char* pName; int index; static int treeCounter; static Tree* pRoot; int freq; int rank; void maxWalk(Tree* node, void (*visit)(Tree* node)); void preWalk(Tree* node, void (*visit)(Tree* node)); void midWalk(Tree* node, void (*visit)(Tree* node)); void postWalk(Tree* node, void (*visit)(Tree* node)); void maxWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr); void preWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr); void midWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr); void postWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr); protected: void* pKey; public: void decCount() {treeCounter --;} const int getRank() { return rank;} void setRank(const int newRank) { rank = newRank;} const int getFreq() {return freq;} void setFreq(const int newFreq) { freq = newFreq;} void setFreq() {freq++;} Tree* left(); Tree* right(); Tree* parent(); virtual void* key(); virtual void setKey(void* newKey); void setRoot(Tree* node); const char* name(); const int getIndex(); void setLeft(Tree* leftSon); void setRight(Tree* rightSon); void setParent(Tree* father); void setIndex(const int number); virtual int compare(const void* otherKey); void setName(const char *str); void giveBirth(); virtual bool operator>(Tree&); virtual bool operator==(Tree&); virtual bool operator<(Tree&); Tree(); virtual ~Tree(); static Tree* root() {return pRoot;} const int count(); void traverse(void ( *visit)(Tree* node), TraverseOrder defaultOrder= MIDORDER, Tree* start= root()); void traverse(void (*visit)(Tree* node, void* userPtr), void* userPtr, TraverseOrder defaultOrder = MIDORDER, Tree* start = root()); };
void visitRank(Tree* node, void* userPtr);
void defaultVisit(Tree* node);
void insertRank(Tree* node, void* userPtr);
class BinaryTree: public Tree { private:
public: virtual void remove(BinaryTree* node); virtual BinaryTree* next(); virtual BinaryTree* prev(); virtual bool insert(BinaryTree* node, BinaryTree* start=(BinaryTree*)root()); virtual ~BinaryTree();
};
class WordTree: public BinaryTree { private: static int wordLength; static int wordCounter; WordTree* addNode(WordTree* node, FILE** stream);
protected: void setWordCounter(); void readWord(FILE** file); void addWord(char* buffer);
public: WordTree* searchWord(WordTree* node, const char* buffer); WordTree* readNode(WordTree* node, FILE** stream); WordTree* readFromFile(const char* fileName); void saveNode(WordTree* node, FILE** stream); virtual int compare(const void *otherKey); void setWordLength(const int newLength); static const int getWordLength(); virtual void setKey(void* newKey); virtual bool operator>(Tree&); virtual bool operator==(Tree&); virtual bool operator<(Tree&); void openFile(const char* fileName); WordTree(const char * fileName); WordTree(); int wordCount(); virtual void setName(const char *str); void saveToFile(const char* fileName); ~WordTree(); virtual WordTree* findWord(const char* buffer); };
class RankTree: public WordTree { private:
protected:
public: virtual bool operator>(Tree& node); virtual bool operator<(Tree& node); void setRankTree(WordTree* wordRoot); RankTree();
};
int count=0;
int main() { WordTree *ptr = new WordTree; char choice[6], fileName[30]; long start =0;
ptr = ptr->readFromFile(DefaultBackup); cout<<"quit? or input?/nEnter your choice: /n"; cin>>choice; while (strcmp(choice, "quit")!=0&&strcmp(choice, "input")!=0) { cout<<"quit? or input?/n Enter your choic: /n"; cin>>choice; } if (strcmp(choice, "quit")==0) { cout<<"The total number of words in dictionary is "<<ptr->wordCount()<<endl; return 0; } else { if (strcmp(choice, "input")==0) { cout<<"/nnow input file name here(input 'quit' to exit):/n"; cin>>fileName; while (strcmp(fileName, "quit")!=0) { start = time(0); ptr->openFile(fileName); cout<<"/nTotal times spent for read file is:"<<time(0) -start<<endl; cout<<"/nnow input file name here(input quit to exit):/n";
cin>>fileName; } cout<<"/nThe total number of words in dictionary is:"<<ptr->count()<<endl; cout<<"/nDo you want to see contents?(yes or no)/n";
cin>>choice;if (strcmp(choice, "yes")==0){ptr->traverse(defaultVisit, PREORDER);}
cout<<"/nDo you want to rank the tree?(yes or no)/n";cin>>choice;if (strcmp(choice, "yes")==0){start = time(0);int rankCount =0;RankTree *rankPtr = new RankTree;ra4000nkPtr->setFreq(ptr->getFreq());rankPtr->setName((char*)ptr->key());
ptr->traverse(insertRank, (void*)rankPtr);
rankPtr->traverse(visitRank, (void*)(&rankCount), MAXORDER, rankPtr);cout<<"/nTotal time for ranking is :"<<time(0) - start<<endl;cout<<"Do you want to see result of ranking?/n";cin>>choice;if (strcmp(choice, "yes")==0){rankPtr->traverse(defaultVisit, MAXORDER, rankPtr);}cout<<"/nThe total number in ranktree is:"<<rankPtr->count()<<endl;}cout<<"The total number of words in dictionary is "<<ptr->wordCount();ptr->saveToFile(DefaultBackup);}}
return 0;}
int WordTree::wordCounter = 0;int WordTree::wordLength = 20;
void insertRank(Tree* node, void* userPtr){RankTree* rankPtr;//rankPtr = (RankTree*)(((RankTree*)userPtr)->searchWord((RankTree*)userPtr,(char*)node->key()));if (rankPtr == NULL){rankPtr = new RankTree;rankPtr->setName((char*)node->key());
rankPtr->setFreq(node->getFreq());((RankTree*)(userPtr))->insert(rankPtr, (RankTree*)userPtr);}}
RankTree::RankTree(){decCount();}
void visitRank(Tree* node, void* userPtr){node->setRank(*(int*)(userPtr));*(int*)(userPtr) +=1;}
bool RankTree::operator <(Tree& node){int result;result = getFreq() - node.getFreq();if (result !=0){return (result<0);}else{return (strcmp((char*)key(), (char*)node.key())<0);}}
bool RankTree::operator >(Tree& node){int result;result = getFreq() - node.getFreq();if (result !=0){return (result>0);}else{return (strcmp((char*)key(), (char*)node.key())>0);}}
void RankTree::setRankTree(WordTree* wordRoot){RankTree* ptr;
if (wordRoot!=NULL){if (this->root()!=NULL){ptr = new RankTree;ptr->setFreq(wordRoot->getFreq());ptr->setKey((void*)wordRoot->key());ptr->insert(ptr);}else{this->setRoot(this);this->setFreq(wordRoot->getFreq());this->setKey((void*)wordRoot->key());}
setRankTree((WordTree*)wordRoot->left());setRankTree((WordTree*)wordRoot->right());}
}
BinaryTree::~BinaryTree(){
}
WordTree::~WordTree(){
}
void WordTree::setWordCounter(){wordCounter ++;}
const int WordTree::getWordLength(){return wordLength;}
WordTree* WordTree::addNode(WordTree* node, FILE** stream){char buffer[MaxWordLength];int index, pIndex, number;WordTree *domino;char *ptr=buffer, ch;
fread((void*)(&index), sizeof(int), 1, *stream);fread((void*)(&pIndex), sizeof(int), 1, *stream);
if (index==-1&&pIndex==-1){return NULL;}
do{ch = fgetc(*stream);*ptr = ch;ptr++;}while(ch!='/0');fread((void*)(&number), sizeof(int), 1, *stream);setWordCounter(); //add a word
if (pIndex== -1) //this is root{node->setIndex(index);node->setFreq(number);node->setName(buffer);node->setRoot(node);return node;}
while (pIndex!=node->getIndex()){if (node->parent()==NULL){return NULL;}node= (WordTree*)node->parent();}
if (node!=NULL&&pIndex==node->getIndex()){domino = new WordTree;domino->setIndex(index);domino->setName(buffer);domino->setFreq(number);domino->setParent(node);if (*domino<*node){node->setLeft(domino);}else{node->setRight(domino);}
return domino;}else{return NULL;}}
WordTree* WordTree::readNode(WordTree* node, FILE** stream){WordTree* domino = node;
while (domino!=NULL){domino = addNode(domino, stream);}return (WordTree*)node->root(); //this is ugly as I have to remove those sentinal}
WordTree* WordTree::readFromFile(const char* fileName){FILE* stream;
if ((stream=fopen(fileName, "r+b"))==NULL){cout<<"unable to open file "<<fileName<<endl;return NULL;}else{WordTree* ptr= new WordTree;return readNode(ptr, &stream);}fclose(stream);}
void WordTree::saveNode(WordTree* node, FILE** stream){int first, second, number;
first = node->getIndex();number = getFreq();
fwrite((void*)(&first), sizeof(int), 1, *stream);if (node->parent()==NULL){second = -1;}else{second = node->parent()->getIndex();}fwrite((void*)(&second), sizeof(int), 1, *stream);fwrite((void*)(node->name()),sizeof(char), strlen(node->name()), *stream);fputc('/0', *stream);//I have to put this '/n' otherwise there is always problem!fwrite((void*)(&number), sizeof(int), 1, *stream);}
void traverseTree(WordTree* node, FILE** stream){if (node!=NULL){node->saveNode(node, stream);traverseTree((WordTree*)node->left(), stream);traverseTree((WordTree*)node->right(), stream);}}
void writeEnd(FILE** stream){int temp1=-1, temp2=-1;fwrite((void*)(&temp1), sizeof(int), 1, *stream);fwrite((void*)(&temp2), sizeof(int), 1, *stream);}
void WordTree::saveToFile(const char* fileName){void traverseTree(WordTree* node, FILE ** stream);void writeEnd(FILE** stream);
WordTree *domino;
FILE * stream;
if ((stream=fopen("c://nickback.txt", "w+b"))==NULL){cout<<"unable to save to file "<<fileName<<endl;}else{domino = (WordTree*)root();traverseTree((WordTree*)domino, &stream);}writeEnd(&stream);fclose(stream);}
const int Tree::count(){return treeCounter;}
void WordTree::setWordLength(const int newLength){if (newLength>MaxWordLength){cout<<"exceed max word length."<<endl;}else{wordLength = newLength;}}
int WordTree::compare(const void*otherKey){return strcmp((char*)key(), (char*)otherKey);}
int WordTree::wordCount(){return wordCounter;}
WordTree::WordTree(){
}
void WordTree::openFile(const char* fileName){FILE * stream;if ((stream=fopen(fileName, "r+b"))==NULL){cout<<"unable open file!"<<endl;}else{readWord(&stream);}fclose(stream);}
void WordTree::readWord(FILE **stream){char buffer[MaxWordLength];char *ptr = buffer;char ch;int counter =0;
while (!feof(*stream)){ptr = buffer;counter = 0;ch = toupper(fgetc(*stream));while (isalnum(ch)&&!feof(*stream)&&counter<wordLength){*ptr = ch;ch = toupper(fgetc(*stream));ptr++;counter++;}
if (ptr!=buffer){*ptr='/0';addWord(buffer);}}}
WordTree* WordTree::searchWord(WordTree* node, const char* buffer){int result;if (node!=NULL){result = strcmp((char*)(node->key()), buffer);if (result ==0){return node;}else{if (result < 0){return searchWord((WordTree*)node->right(), buffer);}else{return searchWord((WordTree*)node->left(), buffer);}}}else{return NULL;}}
WordTree* WordTree::findWord(const char *buffer){return searchWord((WordTree*)root(), buffer);}
void WordTree::addWord(char * buffer){//need add a findword method and find first and then newWordTree *ptr;ptr = findWord(buffer);if (ptr==NULL){ptr = new WordTree;
ptr->setName(buffer);if (ptr->insert(ptr)){setWordCounter();}}else{ptr->setFreq();}}
void WordTree::setName(const char *str){Tree::setName(str);setKey((void*)name());}
int Tree::treeCounter= 0;
WordTree::WordTree(const char* fileName){WordTree::WordTree();openFile(fileName);}
void WordTree::setKey(void * newKey){pKey = newKey;}
bool WordTree::operator <(Tree& second){if (strcmp((char*)key(), (char*)second.key())<0){return true;}else{return false;}}
bool WordTree::operator ==(Tree& second){if (strcmp((char*)key(), (char*)second.key())==0){return true;}else{return false;}}
bool WordTree::operator >(Tree& second){if (strcmp((char*)key(), (char*)second.key())>0){return true;}else{return false;}}
void defaultVisit(Tree* node){cout<<"/n/n";cout<<"default visiting tree index:"<<node->getIndex()<<endl;cout<<"and tree name is:"<<node->name()<<endl;cout<<"and its frequency is: "<<(node)->getFreq()<<endl;cout<<"and its rank is:"<<node->getRank()<<endl;if (node->parent()!=NULL){cout<<"its parent is:"<<node->parent()->name()<<endl;if (node==node->parent()->left()){cout<<"and it is left son."<<endl;}else{cout<<"and it is right son"<<endl;}}else{cout<<"it has no parent"<<endl;}cout<<"/n/n";}
void Tree::preWalk(Tree* node, void (*visit)(Tree* node)){if (node!=NULL){visit(node);preWalk(node->left(), visit);preWalk(node->right(), visit);}}
void Tree::postWalk(Tree* node, void (*visit)(Tree* node)){if (node!=NULL){postWalk(node->left(), visit);postWalk(node->right(), visit);visit(node);}}
void Tree::maxWalk(Tree* node, void (*visit)(Tree* node)){if (node!=NULL){maxWalk(node->right(), visit);visit(node);maxWalk(node->left(), visit);
}}
void Tree::midWalk(Tree* node, void (*visit)(Tree* node)){if (node!=NULL){midWalk(node->left(), visit);visit(node);midWalk(node->right(), visit);}}
void Tree::preWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr){if (node!=NULL){visit(node, userPtr);preWalk(node->left(), visit, userPtr);preWalk(node->right(), visit, userPtr);}}
void Tree::midWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr){if (node!=NULL){midWalk(node->left(), visit, userPtr);visit(node, userPtr);midWalk(node->right(), visit, userPtr);}}
void Tree::postWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr){if (node!=NULL){postWalk(node->left(), visit, userPtr);postWalk(node->right(), visit, userPtr);visit(node, userPtr);}}
void Tree::maxWalk(Tree* node, void (*visit)(Tree* node, void* userPtr), void* userPtr){if (node!=NULL){maxWalk(node->right(), visit, userPtr);visit(node, userPtr);maxWalk(node->left(), visit, userPtr);}}
void Tree::traverse(void (*visit)(Tree* node, void* userPtr), void* userPtr,TraverseOrder defaultOrder, Tree* start){Tree *domino;domino = start;
switch(defaultOrder){case PREORDER:preWalk(domino, visit, userPtr);break;case MIDORDER:midWalk(domino, visit, userPtr);break;case POSTORDER:postWalk(domino, visit, userPtr);break;case MAXORDER:maxWalk(domino, visit, userPtr);break;}}
void Tree::traverse(void (*visit)(Tree* node), TraverseOrder defaultOrder, Tree* start){Tree *domino;domino = start;
switch(defaultOrder){case PREORDER:preWalk(domino, visit);break;case MIDORDER:midWalk(domino, visit);break;case POSTORDER:postWalk(domino, visit);break;case MAXORDER:maxWalk(domino, visit);break;}}
Tree* Tree::pRoot = NULL;
void BinaryTree::remove(BinaryTree* node){BinaryTree* ptr=NULL;
if (node->left()==NULL || node->right()==NULL){if (node->left()!=NULL){node->parent()->setLeft(node->left());node->left()->setParent(node->parent());}if (node->right()!=NULL){node->parent()->setRight(node->right());node->right()->setParent(node->parent());}}else{ptr = node->next();remove(ptr);ptr->setParent(node->parent());if (node->parent()==NULL){node->setRoot(ptr);}else{if (node==node->parent()->left()){node->parent()->setLeft(ptr);}else{node->parent()->setRight(ptr);}ptr->setLeft(node->left());ptr->setRight(node->right());}}}
bool Tree::operator==(Tree& second){if (this->compare(second.key())==0){return true;}else{return false;}}
bool Tree::operator <(Tree& second){if (this->compare(second.key())<0){return true;}else{return false;}}
bool Tree::operator >(Tree& second){if (this->compare(second.key())>0){return true;}else{return false;}}
int Tree::compare(const void * otherKey){return *((int*)(key()))- *((int*)(otherKey));}
void* Tree::key(){return pKey;}
void Tree::setKey(void *newKey){pKey = malloc(sizeof(int));*(int*)(pKey) = *(int*)(newKey);}
void Tree::setRoot(Tree *node){pRoot = node;}
bool BinaryTree::insert(BinaryTree* node, BinaryTree* start){Tree* ptr, *dummy;
ptr = start;dummy = ptr;while (ptr!=NULL){dummy = ptr;if (*ptr>*node){ptr = ptr->left();}else{if (*ptr<*node){ptr=ptr->right();}else{if (*ptr==*node){return false;}}}}
node->setParent(dummy);
if (dummy==NULL){setRoot(node);}else{// node->setRoot(dummy->root());if (*dummy>*node){dummy->setLeft(node);}else{if (*dummy<*node){dummy->setRight(node);}} //if "== ", donot insert;}return true;}
void Tree::setLeft(Tree* leftSon){pLeft = leftSon;}
void Tree::setRight(Tree* rightSon){pRight = rightSon;}
void Tree::setParent(Tree* father){pParent = father;}
void Tree::giveBirth(){Tree* leftTree = new Tree;Tree* rightTree = new Tree;char str[128];
leftTree->setIndex(this->getIndex() *2 );rightTree->setIndex(this->getIndex() * 2 + 1);
this->setLeft(leftTree);this->setRight(rightTree);
leftTree->setParent(this);rightTree->setParent(this);
strcpy(str, "left son of ");strcat(str, this->name());
leftTree->setName(str);
strcpy(str, "right son of ");strcat(str, this->name());
rightTree->setName(str);
leftTree->setParent(this);rightTree->setParent(this);
if (root()==NULL){setRoot(this);setParent(NULL);}/*else{leftTree->setRoot(root());rightTree->setRoot(root());}*/}
void Tree::setIndex(const int number){index = number;}
const int Tree::getIndex(){return index;}
const char* Tree::name(){return pName;}
void Tree::setName(const char *str){if (str!=NULL){pName = (char *)malloc(strlen(str)+1);strcpy(pName, str);}}
Tree::Tree(){setIndex(treeCounter);treeCounter++;pLeft = NULL;pRight = NULL;pParent = NULL;pName = NULL;pKey = NULL;freq = 0;rank =0;}
Tree::~Tree(){if (pName!=NULL){free(pName);}if (pKey!=NULL){free(pKey);}}
Tree* Tree::left(){return pLeft;}
Tree* Tree::right(){return pRight;}
Tree* Tree::parent(){return pParent;}
BinaryTree* BinaryTree::next(){Tree* result = NULL;
if (right()!=NULL){result = right();while (result->left!=NULL){result = result->left();}}else{if (parent()!= NULL){result = this;while(ra025esult->parent()!=NULL&&result==result->parent()->right()){result = result->parent();}}//result = null}return (BinaryTree*)result;}
BinaryTree* BinaryTree::prev(){Tree* result = NULL;if (left()!=NULL){result = left();while (result->right()!=NULL){result = result->right();}}else{if (parent()!=NULL){result = this;while (result->parent()!=NULL&&result==result->parent()->left()){result = result->parent();}}}return (BinaryTree*)result;}
![](http://www3.sympatico.ca/qingzhehuang/picture/back.gif)
![](http://www3.sympatico.ca/qingzhehuang/picture/up.gif)
![](http://www3.sympatico.ca/qingzhehuang/picture/next.gif)
相关文章推荐
- 一个应用二叉搜索树实现的字典,并存储结构于文件中 选择自 nickhuang2002 的 Blog
- 二叉搜索树应用-判断一个单词是否拼写正确,实现简单字典
- 模拟实现一个简单的中英互译字典——二叉搜索树的应用KV模型
- 算法应用:用递归结构实现穷举服务器文件
- [PHP][Function]实现将一个文件夹下的所有文件及文件夹复制到另一个文件夹里(保持原有结构)[已验证][原创]
- Java编程的逻辑 (61) - 内存映射文件及其应用 - 实现一个简单的消息队列
- Java编程的逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库
- 请实现一个算法,确定一个字符串的所有字符是否全都不同。这里我们要求不允许使用额外的存储结构。
- 九宫格 Swift提供经典的数组和字典两种集合类型来存储集合数据,使用数组实现一个九宫格程序,
- 一个图的带权邻接表存储结构的应用
- 在/sys目录下建立一个文件,并且实现信息的读取和存储
- 对象序列化的应用,一个文件中存储多个对象
- 用Express和MongoDB实现一个简单的图片存储应用
- 在/sys目录下建立一个文件,并且实现信息的读取和存储
- 请实现一个算法,确定一个字符串的所有字符是否全都不同。这里我们要求不允许使用额外的存储结构。 给定一个string iniString,请返回一个bool值,True代表所有字符全都不同,False代
- 在/sys目录下建立一个文件,并且实现信息的读取和存储
- C语言 文件I/O:实现结构体数据 存储到文件和从文件读取
- java实现以树结构打印一个文件目录结构
- 用java实现一个单线程基于控制台和以文件为数据存储并加上一点MVC思想的ATM
- 数据结构(C实现)------- 顺序队列(循环队列之少用一个存储空间实现) .