最近阅读《虚拟机的设计与实现-c/c++》发现第五章中哈希表的实现算法有点小bug,我对它算法做了一些修改并除掉了bug,如果按照书上的代码,大家一定会遇到 link2001 "0x..........."not read "0x............."是什么原因呢 其实此类问题是很严重的关于内存操作问题 就是变量没有初始化 对此例中的问题是在构造函数左右孩子没有初始化设置为null, 注意事项:1 大家应该尽量避免使用二重指针,二重指针很复杂,容易出错,应该适当的应用引用。 2 使用变量时一定要初始化,使用完后应该回收 尤其是以new申请的内存区域或指针。 必须回收 方法:例如: struct HashT * link = new struct HashT; delete link; //必须 link= NULL://必须 3 要养成良好的编程风格。 此代码在vc6.0测试过, 如有问题发送我到[email protected] ,谢谢。 代码解析: //hashtable.cpp #include"hashtable.h" HashTable::HashTable() { int i; for(i=0;i<PRIME;i++) { hashT[i].empty =true; hashT[i].Field_Name[0]='\0'; hashT[i].left = NULL;//必须初始化 hashT[i].right = NULL;//必须初始化 } } HashTable::~HashTable() { int i; for(i=0;i<PRIME;i++) { deleteAll((hashT[i].left)); deleteAll((hashT[i].right)); } } struct HashT* HashTable::queryHashT(char * str) { int hash; hash =hashpjw(str); if(hashT[hash].empty==true) { return(NULL); } else { return ( findNode((&hashT[hash]),str)); } } void HashTable::addHashT(char * val) { struct HashT * ptr; int hash; hash=hashpjw(val); printf("HashTable.addHashT():hash(%s)=%d\n",val, hash); if(hashT[hash].empty==true) { hashT[hash].empty=false; strcpy(hashT[hash].Field_Name,val); hashT[hash].left =NULL; hashT[hash].right= NULL; return; } ptr =&hashT[hash]; insertNode(ptr,val); } void HashTable::printHashT() { int i; for(i=0;i<PRIME;i++) { if(hashT[i].empty==false) { printf("--Hash Slot (%d)--\n",i); printTree(&(hashT[i]),0); printf("\n"); } } printf("\n"); } int HashTable::hashpjw(char *s) { unsigned char * p; unsigned h=0,g; for(p=((unsigned char * )s); * p!='\0';p=p+1) { h=(h<<4)+(*p); if(g=(h&0xf0000000)) { h=h^(g>>24); h=h^g; } } return h%PRIME; } struct HashT * HashTable::findNode(struct HashT * link, char * val) { if(link==NULL) { return(NULL); } else if(strcmp(val,link->Field_Name)==0) { return(link); } else if(strcmp(val,link->Field_Name)>0) { return(findNode(link->right,val)); } else { return(findNode(link->left,val)); } } void HashTable::insertNode (struct HashT * &link, char *val) { if(link==NULL) { link= new struct HashT;//ÉêÇëÄÚ´æ link->empty =false; strcpy(link->Field_Name, val); link->left = NULL; link->right = NULL; } else if (strcmp(val,link->Field_Name)==0) { printf("HashTable.insertNode():redundant identifier %s\n",val); } else if (strcmp(val,link->Field_Name)<0) { insertNode(link->left,val); } else { insertNode(link->right,val); } } void HashTable::printTree(struct HashT * link, int level) { int i; if(link!=NULL) { printTree(link->right,level+1); for(i=0;i<level;i++) { printf("-"); } printf("identifer=%s\n",link->Field_Name); printTree(link->left,level+1); } } void HashTable::deleteAll(struct HashT *& link) { if(link!=NULL) { deleteAll(link->left); deleteAll(link->right); printf("HashTable.deleteAll():freeing %s \n",link->Field_Name); delete link; link =NULL; } } //hashtable.h #include<stdio.h> #include<string.h> #include<malloc.h> struct HashT { bool empty; char Field_Name[32]; struct HashT * left; struct HashT * right; }; #define PRIME 13 class HashTable { private: struct HashT hashT[PRIME]; int hashpjw(char *s); struct HashT * findNode(struct HashT * link, char * val); void insertNode (struct HashT * &link, char *val); void printTree(struct HashT * link, int level); void deleteAll(struct HashT * &link); public: HashTable(); ~HashTable(); struct HashT * queryHashT(char * str); void addHashT(char * val); void printHashT(); };
#include"hashtable.h" int main() { char str[32]; HashTable ht; char * FieldArray[2]={"CallingNO","CalledNO"}; ht.addHashT("CallingNO"); ht.addHashT("CalledNO"); ht.printHashT(); for (int i=0;i<2;i++) { strcpy(str,FieldArray[i]); if((ht.queryHashT(str))!=NULL) { printf("found %s\n",str); } else { printf("did not find %s\n",str); } } return 0 ; } 
|