从标准输入中读入一个英文单词及查找方式,在一个给定的英文常用单词字典文件dictionary3000.txt中查找该单词,返回查找结果(查找到返回1,否则返回0)和查找过程中单词的比较次数。查找前,先将所有字典中单词读入至一个单词表(数组)中,然后按要求进行查找。字典中单词总数不超过3500,单词中的字符都是英文小写字母,并已按字典序排好序(可从课件下载区下载该字典文件)。字典中的单词和待查找单词的字符个数不超过20。
查找方式说明:查找方式以1~4数字表示,每个数字含义如下:
1:在单词表中以顺序查找方式查找,因为单词表已排好序,遇到相同的或第一个比待查找的单词大的单词,就要终止查找;
2:在单词表中以折半查找方式查找;
3:在单词表中通过索引表来获取单词查找范围,并在该查找范围中以折半方式查找。索引表构建方式为:以26个英文字母为头字母的单词在字典中的起始位置和单词个数来构建索引表,如:
字母 | 起始位置 | 单词个数 |
a | 0 | 248 |
b | 248 | 167 |
… | … | … |
该索引表表明以字母a开头的单词在单词表中的开始下标位置为0,单词个数为248。
4:按下面给定的hash函数为字典中单词构造一个hash表,hash冲突时按字典序依次存放单词。hash查找遇到冲突时,采用链地址法处理,在冲突链表中找到或未找到(遇到第一个比待查找的单词大的单词或链表结束)便结束查找。
/* compute hash value for string */
#define NHASH 3001
#define MULT 37
unsigned int hash(char *str)
{
unsigned int h=0;
char *p;
for(p=str; *p!='\0'; p++)
h = MULT*h + *p;
return h % NHASH;
}
提示:hash表可以构建成指针数组,hash冲突的单词形成一有序链表。
【输入形式】
单词字典文件dictionary3000.txt存放在当前目录下,待查找单词和查找方式从标准输入读取。待查找单词只包含英文小写字母,与表示查找方式的整数之间以一个空格分隔。
【输出形式】
将查找结果和单词比较次数输出到标准输出上,两整数之间以一个空格分隔。
【样例输入与输出】
单词字典文件dictionary3000.txt与课件下载中提供的相同,下面两列中,左侧为待查找单词与查找方式,右侧为对应的输出结果:
wins 1 0 3314
wins 2 0 12
wins 3 0 7
wins 4 0 2
yes 1 1 3357
yes 2 1 10
yes 3 1 4
yes 4 1 1
【样例说明】
wins在单词字典中不存在,4种查找方式都输出结果0,顺序查找、折半查找、索引查找和hash查找的单词比较次数分别为:3314、12、7和2次(wins的hash位置与字典中physics和suggest相同)。
yes在单词字典中存在,4种查找方式都输出结果1,顺序查找、折半查找、索引查找和hash查找的单词比较次数分别为:3357、10、4和1。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct word_list{
char word[26];
};
struct word_list word_block[3510];
struct index{
char alpha;
int start;
int all;
};
struct index index_list[26];
#define NHASH 3001
#define MULT 37
unsigned int hash(char *str)
{
unsigned int h=0;
char *p;
for(p=str; *p!='\0'; p++)
h = MULT*h + *p;
return h % NHASH;
}
typedef struct node{
char word[26];
struct node *link;
}LNode, *LinkList;
void order_search(struct word_list word_block[], char obj[]);
void bisearch(struct word_list word_block[], char obj[] );
void index_search(struct index index_list[], char obj[] );
void insert(LinkList list, char temp[]);
int total = 0;
int main()
{
FILE *in;
in = fopen("dictionary3000.txt","r");
int i = 0, method, times = 0, loop = 0; /*i is the total number of all words, times marks times of comparing in search*/
char temp[26], obj[26];
char head_letter = 'a';
int j = 1, all1 = 0;
int hash_value;
LinkList list = NULL, p;
LinkList hash_list[3002];
for(loop = 0; loop<3002; loop++)
{
list = (LinkList)malloc(sizeof(LNode));
list->link = NULL;
hash_list[loop] = list;
}
for(loop=0; loop<26; loop++)
{
index_list[loop].alpha = 'a' + loop;
index_list[loop].all = 0;
index_list[loop].start = 0;
}
index_list[0].alpha = 'a';
index_list[0].start = 0;
while( !feof(in) )
{
fscanf(in, "%s", &temp);
strcpy(word_block[i].word, temp);
index_list[temp[0]-'a'].all++;
if( temp[0] != head_letter )
{
head_letter++;
index_list[temp[0]-'a'].start = i;
}
hash_value = hash(temp); /*计算出它的哈希值*/
if( hash_list[hash_value]->link == NULL )
{
p = hash_list[hash_value];
strcpy(p->word, temp);
p->link = NULL;
}
else if( hash_list[hash_value]->link != NULL )
{
insert(hash_list[hash_value], temp);
}
i++;
}
index_list['z'-'a'].all--;
total = i-1;
scanf("%s %d", &obj, &method);
if( method == 1) /*order search*/
{
order_search(word_block, obj);
}
else if(method ==2)
{
bisearch(word_block, obj);
}
else if (method == 3)
{
index_search(index_list, obj);
}
else if(method == 4)
{
hash_value = hash(obj);
p = hash_list[hash_value]; /*hash value is a head pointer*/
times++;
while( strcmp(p->word , obj) > 0 && p->link != NULL)
{
p = p->link;
times++;
}
if( strcmp(p->word , obj) == 0)
{
printf("1 %d\n", times);
}
else
{
printf("0 %d\n", times+1);
}
}
fclose(in);
return 0;
}
void order_search(struct word_list word_block[], char obj[])
{
int i = 0, times = 0;
for(i = 0; i<=3500; i++ )
{
times++;
if( strcmp(obj, word_block[i].word ) > 0 )
continue;
else if( strcmp(obj, word_block[i].word ) == 0 )
{
printf("1 %d\n", times);
break;
}
else {
printf("0 %d\n", times);
break;
}
}
}
void bisearch( struct word_list word_block[], char obj[] )
{
int low = 0, high = total-1, mid, times = 0, find = 0;
while ( low<=high ){
times++;
mid = (low + high)/2;
if( strcmp( word_block[mid].word, obj ) ==0 )
{
printf("1 %d\n", times);
find = 1;
break;
}
else if( strcmp( word_block[mid].word, obj ) < 0)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
if(find == 0)
{
printf("0 %d\n", times);
}
}
void index_search( struct index index_list[], char obj[] )
{
int low = index_list[obj[0]-'a'].start , high = low+index_list[obj[0]-'a'].all-1 , mid, times = 0, find = 0;
while ( low<=high ){
times++;
mid = (low + high)/2;
if( strcmp( word_block[mid].word, obj ) ==0 )
{
printf("1 %d\n", times);
find = 1;
break;
}
else if( strcmp( word_block[mid].word, obj ) < 0)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
if(find == 0)
{
printf("0 %d\n", times);
}
}
void insert(LinkList list, char temp[]) /*大指针数组内的某个元素 是该链表的头结点*/
{
LinkList p, r;
r = list; /*wei zhi zhen */
while(r->link != NULL)
{
r = r->link;
}
p = (LinkList)malloc(sizeof(LNode));
strcpy(p->word, temp);
p->link = NULL;
r->link = p;
}