如果我们刚刚计算出“excel”的散列函数,那么我们就不必再从头开始计算“excel”的散列函数。调整散列函数使得它能够利用前面的计算
2016-05-16 21:37
621 查看
数据结构与算法分析——c语言描述 练习5.13 c 答案
前面几道单独的习题的组合。虽然没什么新意,思路一看就懂。但我竟然写了4个小时!!!!!!!!!
下午写的时候插入单词没问题,4重循环外面找单词没问题,但循环里面找就不行了。里面我也没修改散列表啊,只用了find函数,根本没修改。找不到问题,晚上重新写,想了半小时还是觉得下午的思路没错,并且是最好的。改一下变量名,完善一下代码格式规范竟然好了。。。。
1.代码规范要好,我原本枚举里面的类型是用小写的,后来改成大写bug就自动消失了。。。。。
2.指定长度的字符串(mystrcmp)比较要考虑全面。一个bug就是这个问题出现的。现象是init空间太小就会把前缀改成单词。就是这个函数没写好。使以为前面插入的前缀和现在插入的单词以为是相同的。
思考再写代码。切记切记。不要盲目使用printf大法,printf的是人品。。。。
输入的是课本上开始的例子
hashQuad.h
main.cpp
生成随机字符串,和上面的没关系,用来测试rehash时用的
前面几道单独的习题的组合。虽然没什么新意,思路一看就懂。但我竟然写了4个小时!!!!!!!!!
下午写的时候插入单词没问题,4重循环外面找单词没问题,但循环里面找就不行了。里面我也没修改散列表啊,只用了find函数,根本没修改。找不到问题,晚上重新写,想了半小时还是觉得下午的思路没错,并且是最好的。改一下变量名,完善一下代码格式规范竟然好了。。。。
1.代码规范要好,我原本枚举里面的类型是用小写的,后来改成大写bug就自动消失了。。。。。
2.指定长度的字符串(mystrcmp)比较要考虑全面。一个bug就是这个问题出现的。现象是init空间太小就会把前缀改成单词。就是这个函数没写好。使以为前面插入的前缀和现在插入的单词以为是相同的。
思考再写代码。切记切记。不要盲目使用printf大法,printf的是人品。。。。
输入的是课本上开始的例子
4 4 this two fat that this wats oahg fgdt
hashQuad.h
enum KindOfStr { PREFIX, WORD }; struct ElementType { char *str; enum KindOfStr infoOfStr; }; #ifndef _HashQuad_H #define _HashQuad_H typedef unsigned int Index; typedef Index Position; struct HashTbl; typedef struct HashTbl* HashTable; HashTable initializeTable(int tableSize); void destroyTable(HashTable h); Position find(const char *s, int len, HashTable h); HashTable insert(char *s, int len, KindOfStr infoOfStr, HashTable h); HashTable rehash(HashTable h); ElementType retrive(Position p, HashTable h); int isLegitimate(Position pos, HashTable h); HashTable insertWord(char *word,HashTable h); #endif
#include"hashQuad.h" #include"fatal.h" #include<math.h> #include<string.h> #define MinTableSize 10 enum KindOfEntry { Legitimate, Empty, Deleted }; struct HashEntry { ElementType element; enum KindOfEntry info; }; typedef struct HashEntry Cell; struct HashTbl { int tableSize; int hasInsertedNum; Cell *theCells;//数组 }; static int hash(const char * key, int len, int tableSize) { unsigned int hashVal = 0; while (len--) hashVal = (hashVal << 5) + *key++; return hashVal % (tableSize); } static int isPrime(int num) { for (int i = 2; i <= sqrt(num); i++) if (num%i == 0) return 0; return 1; } static int nextPrime(int num) { int i = num; while (!isPrime(i)) i++; return i; } static int mystrcmp(char *s1, const char *s2, int len) { while (len&& *s1 != '\0'&& *s2 != '\0') { if (*s1 != *s2) return *s1 - *s2; s1++; s2++; len--; } if (!len) return *s1 - '\0';//指定s2的长度(少于实际长度),结束的时候当然是用假设的'\0',s1可能比s2长,相等 return 1;//s1比s2短,不相等 } static void mystrcpy(char *s1, char *s2, int len) { while (len--) { *s1 = *s2; s1++; s2++; } *s1 = '\0'; } int isLegitimate(Position pos, HashTable h) { return h->theCells[pos].info == Legitimate; } static HashTable insert(char *s, int len, enum KindOfStr info, HashTable h, unsigned int *hashRecord) { if ((double)h->hasInsertedNum / h->tableSize > 0.5) h = rehash(h); Position currentPos; *hashRecord = ((*hashRecord) * 32 + *(s + len - 1)); currentPos = (*hashRecord) % h->tableSize; while (h->theCells[currentPos].info != Empty && mystrcmp(h->theCells[currentPos].element.str, s, len) != 0) { currentPos = (currentPos + 1) % h->tableSize; } if (h->theCells[currentPos].info != Legitimate) { h->theCells[currentPos].element.str = (char *)malloc(sizeof(char)*len + 1); mystrcpy(h->theCells[currentPos].element.str, s, len); h->theCells[currentPos].element.infoOfStr = info; h->theCells[currentPos].info = Legitimate; h->hasInsertedNum++; } else {// 存在相同的字符串 if (h->theCells[currentPos].element.infoOfStr == PREFIX) h->theCells[currentPos].element.infoOfStr = info;//可以直接赋值,值可能为PREFIX或WORD } return h; } HashTable insertWord(char * word, HashTable h) { int j; int len = strlen(word); unsigned int hashRecord = 0; for (j = 1; j < len; j++) {//插入前缀 h = insert(word, j, PREFIX, h, &hashRecord); } h = insert(word, j, WORD, h, &hashRecord);//插入单词 return h; } HashTable initializeTable(int tableSize) { HashTable h; int i; if (tableSize < MinTableSize) { Error("Table size too small"); return NULL; } h = (HashTable)malloc(sizeof(struct HashTbl)); if (h == NULL) FatalError("Out of space!!!"); h->tableSize = nextPrime(tableSize); h->theCells = (Cell *)malloc(sizeof(Cell)*h->tableSize); h->hasInsertedNum = 0; if (h->theCells == NULL) FatalError("Out of space!!!"); for (i = 0; i < h->tableSize; i++) { h->theCells[i].info = Empty; } return h; } void destroyTable(HashTable h) { for (int i = 0; i < h->tableSize; i++) if (h->theCells[i].info == Legitimate) free(h->theCells[i].element.str); free(h->theCells); free(h); } Position find(const char *s, int len, HashTable h) { Position currentPos = hash(s, len, h->tableSize); while (h->theCells[currentPos].info != Empty && mystrcmp(h->theCells[currentPos].element.str, s, len) != 0) { currentPos = (currentPos + 1) % h->tableSize; } return currentPos; } HashTable insert(char *s, int len, enum KindOfStr infoOfStr, HashTable h) { if ((double)h->hasInsertedNum / h->tableSize > 0.5) h = rehash(h); Position pos = find(s, len, h); if (h->theCells[pos].info != Legitimate) { h->theCells[pos].element.str = (char *)malloc(sizeof(char)*len + 1); mystrcpy(h->theCells[pos].element.str, s, len);// h->theCells[pos].element.infoOfStr = infoOfStr; h->theCells[pos].info = Legitimate; h->hasInsertedNum++; } else {//已存在相同的字符串。若插入的是单词,存在的是前缀,改 if (h->theCells[pos].element.infoOfStr == PREFIX) h->theCells[pos].element.infoOfStr = infoOfStr; } return h; } static HashTable insert(ElementType key, HashTable h) { if ((double)h->hasInsertedNum / h->tableSize > 0.5) h = rehash(h); Position pos = find(key.str, strlen(key.str), h); if (h->theCells[pos].info != Legitimate) { h->theCells[pos].element.str = (char *)malloc(sizeof(char)*strlen(key.str) + 1); strcpy(h->theCells[pos].element.str, key.str); h->theCells[pos].element.infoOfStr = key.infoOfStr; h->theCells[pos].info = Legitimate; h->hasInsertedNum++; } return h; } HashTable rehash(HashTable h) { HashTable newH = initializeTable(h->tableSize * 2); for (int i = 0; i < h->tableSize; i++) if (h->theCells[i].info == Legitimate) insert(h->theCells[i].element, newH); destroyTable(h); return newH; } ElementType retrive(Position p, HashTable h) { return h->theCells[p].element; }
main.cpp
#include<stdlib.h> #include<stdio.h> #include<string.h> #include<string> #include"hashQuad.h" #define MAXN 100 #define N 1000 #define LEN 40 char dictionary[MAXN][MAXN]; char table[MAXN][MAXN];//字谜 //由上顺时针旋转一圈 int dx[8] = { 0,1,1,1,0,-1,-1,-1 }; int dy[8] = { 1,1,0,-1,-1,-1,0,1 }; int dic_num, n; int main() { HashTable h = initializeTable(10);//小于30出问题 scanf("%d%d", &dic_num, &n); for (int i = 0; i < dic_num; i++) { scanf("%s", dictionary[i]); h = insertWord(dictionary[i], h); } for (int i = 0; i < n; i++) { scanf("%s", table[i]); } int dirChangedCnt = 0; printf("\n"); for (int r = 0; r < n; r++) {//行 for (int c = 0; c < n; c++) {//列 for (int d = 0; d < 8; d++) {//方向 std::string s; int rr = r; int cc = c; for (int l = 1; l <= n; l++) {//长度 s += table[rr][cc]; rr += dx[d]; cc += dy[d]; Position pos = find(s.c_str(), s.length(), h); if (isLegitimate(pos, h) && retrive(pos, h).infoOfStr == WORD) printf("%s\n", s.c_str()); else if (!isLegitimate(pos, h)) {//找不到前缀 dirChangedCnt++; break;//找不到,换方向 } } } } } printf("direction has changed %d times\n", dirChangedCnt); }
生成随机字符串,和上面的没关系,用来测试rehash时用的
#define N 1000 #define LEN 40 int randInt(int i, int j) { int temp; temp = (int)(i + (1.0*rand() / RAND_MAX)*(j - i)); return temp; } void getRandStr(char s[][LEN],int n) { for (int i = 0; i < n; i++) { int len = randInt(1, LEN-1); int j; for ( j = 0; j < len; j++) s[i][j] = randInt(33, 126);//可打印字符的ascii区间 s[i][j] = '\0'; } } char s [LEN]; getRandStr(s,N);
相关文章推荐
- 【设计模式】桥接模式
- 15.10.4 捕获异常
- linux-vim 文本编辑器快捷键--附键位分布图
- [Ruby笔记]3. 语法检查ruby -cw xx.rb /代码运行 ruby xx.rb/变量约定 @ @@ $
- c语言main函数的argc和argv[]参数问题
- uva 10902 Pick-up Sticks
- XMPPFramework,编译失败,@import libxmlSimu后提示:Module 'libxmlSimu' not found
- Qt相关问题
- 下拉菜单demo---参考阿里云首页顶部下拉菜单
- 关于linux启动
- 杭电 2053(循环)
- Android常用控件
- Box2d源码学习<十二>b2Collision之碰撞(上)公共部分的实现
- redis常见的五种数据类型
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- Syntax error, parameterized types are only available if source level is 1.5 解决方案
- [leetcode] 239. Sliding Window Maximum
- HDU 2586 How far away ? 离线LCA
- 欢迎使用CSDN-markdown编辑器