储存每一个单词W以及W的所有前缀,特定方的方向执行一次扫描的时候,如果被查找的单词作为前缀不在散列表中,那么在这个方向上可以及早终止

来源:互联网 发布:linux c语言ide 编辑:程序博客网 时间:2024/05/22 06:37

数据结构与算法分析——c语言描述 练习5.13 b 答案


1.重写了字符串复制和比较的函数,指定了长度,假如用原来的要求'\0'结尾,那么每增加一个前缀都要复制一次单词。严重浪费。

2.就是储存单词的同时加上是前缀还是单词。考虑一下相同的单词,一个前缀,一个单词。更改属性。


hashQuad.h

enum KindOfStr{ Prefix,word };struct ElementType {char *s;enum KindOfStr info;};#ifndef _HashQuad_H#define _HashQuad_Htypedef 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, enum KindOfStr info, HashTable h);HashTable rehash(HashTable h);ElementType retrive(Position p, HashTable h);int isLegitimate(Position pos, HashTable h);#endif

hashQuad.cpp

#include"hashQuad.h"#include"fatal.h"#include<math.h>#include<string.h>#define MinTableSize 10enum 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;}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.s);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.s, s, len) != 0) {currentPos = (currentPos + 1) % h->tableSize;}return currentPos;}HashTable insert(char *s, int len, enum KindOfStr info, 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.s = (char *)malloc(sizeof(char)*strlen(s) + 1);mystrcpy(h->theCells[pos].element.s, s, len);//h->theCells[pos].element.info = info;h->theCells[pos].info = Legitimate;h->hasInsertedNum++;}else {//已存在相同的字符串。若插入的是单词,存在的是前缀,改if (h->theCells[pos].element.info == PREFIX)h->theCells[pos].element.info = info;}return h;}static HashTable insert(ElementType key, HashTable h) {if ((double)h->hasInsertedNum / h->tableSize > 0.5)h = rehash(h);Position pos = find(key.s, strlen(key.s), h);if (h->theCells[pos].info != Legitimate) {h->theCells[pos].element.s = (char *)malloc(sizeof(char)*strlen(key.s) + 1);strcpy(h->theCells[pos].element.s, key.s);h->theCells[pos].element.info = key.info;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<stdio.h>#include<string>#include<algorithm>#include"hashQuad.h"#define MAXN 100char 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() {int i;HashTable h = initializeTable(100);scanf("%d%d", &dic_num, &n);for (i = 0; i < dic_num; i++) {scanf("%s", dictionary[i]);int j;for (j = 1; j < (int)strlen(dictionary[i]); j++) {//插入前缀h = insert(dictionary[i], j, Prefix, h);}h = insert(dictionary[i], j, word, h);//插入单词}for (i = 0; i < n; i++) {scanf("%s", table[i]);}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).info == word)printf("%s\n", s.c_str());else if (!isLegitimate(pos, h)) {//找不到前缀break;//找不到,换方向}}}}}}


0 0