哈希表查找(C语言实现)

/*
 * 题目:给定一个全部由字符串组成的字典,字符串全部由大写字母构成。其中为每个字符串编写密码,编写的
 *       方式是对于 n 位字符串,给定一个 n 位数,大写字母与数字的对应方式按照电话键盘的方式:
 *         2: A,B,C     5: J,K,L    8: T,U,V
 *         3: D,E,F     6: M,N,O    9: W,X,Y,Z
 *         4: G,H,I     7: P,Q,R,S
 * 题目给出一个1--12位的数,找出在字典中出现且密码是这个数的所有字符串。字典中字符串的个数不超过5000。
 *        
 * 思路:1.回溯法找出所有可能的字符串
 *       2.在字典中查找此字符串是否存在。(字典存储采用哈希表存储) 
 *
 */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define HASHTABLE_LENGTH 5001  //哈希表长度
#define STRING_LENGTH   13     //单词最大长度

//字符串
typedef struct
{
	char str[STRING_LENGTH];
	int length;
}HString;

HString string={'\0',0};             //暂存可能的字符串
HString hashTable[HASHTABLE_LENGTH]; //哈希表

//hash函数,构造哈希表
void createHashTable(char *str)
{
	int i,key,step=1;
	i=key=0;
	while(str[i]){
		key+=str[i++]-'A';
	}
	key%=HASHTABLE_LENGTH;
	while(1){
		if(hashTable[key].length==0){
			hashTable[key].length=strlen(str);
			strcpy(hashTable[key].str,str);
			break;
		}
		key=(key+step+HASHTABLE_LENGTH)%HASHTABLE_LENGTH;
		//处理冲突,线性探测再散列
		if(step>0)
    		step=-step;
		else{
			step=-step;
			step++;
		}
	}
}

//从文件中读字典
void readString()
{
	int i;
	char str[STRING_LENGTH];
	char ch;
	FILE *fp;
    if((fp=fopen("document/dictionary.txt","r"))==NULL){   
       printf("can not open file!\n");   
       exit(0);   
    }  
	
    i=0;
    while((ch=getc(fp))!=EOF){   
        if(ch=='\n'){//读完一个字符串
			str[i]='\0';
            createHashTable(str);
			i=0;
			continue;
		}
		str[i++]=ch;
	}

    if(fclose(fp)){   
        printf("can not close file!\n");   
        exit(0);   
    }   
}

//在哈希表中查找是否存在该字符串,存在返回1,不存在返回0
int search(char *str)
{
	int i,key,step=1;
	i=key=0;
	while(str[i]){
		key+=str[i++]-'A';
	}
	key%=HASHTABLE_LENGTH;
	while(1){
		if(hashTable[key].length==0)
			return 0;
		if(strcmp(hashTable[key].str,str)==0){
			return 1;
		}
		key=(key+step+HASHTABLE_LENGTH)%HASHTABLE_LENGTH;
		//处理冲突,线性探测再散列
		if(step>0)
    		step=-step;
		else{
			step=-step;
			step++;
		}
	}
	return 0;
}

//求所有可能的字符串
void getString(char* num)
{
	int i,digit,max;
	if(*num==0){//递归出口,字符串已到末尾
		string.str[string.length]='\0';
        if(search(string.str))//这个字符串存在于字典中,输出
			puts(string.str);
		return;
	}

	digit=*num-'0';//取第一位字符,转成数字
	if(digit>=2&&digit<=6){
		i=(digit-2)*3+'A';
		max=(digit-2)*3+'A'+3;
	}
	else if(digit==7){
		i='P';
		max='P'+4;
	}
	else if(digit==8){
		i='T';
		max='T'+3;
	}
	else if(digit==9){
		i='W';
		max='W'+4;
	}

	for(i;i<max;i++){
		string.str[string.length++]=i;
        getString(num+1); //递归
		string.length--;
	}
}

void main()
{
	char num[STRING_LENGTH];   //由于输入的数字超出了unsigned long的范围,所以用字符串来存储
	readString();              //把字典从文件中读入内存
    printf("please inputer an number(1--12位,不能有0或1)\n");
    scanf("%s",num);
	getString(num);
}


 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表是一种利用哈希函数进行快速查找的数据结构。C语言可以通过数组和指针实现哈希表。 首先需要定义一个哈希函数,将关键字转换成哈希表的位置。可以使用简单的取模运算,将关键字的值除以哈希表大小取余数得到哈希表位置。 例如,哈希表大小为10,关键字为20,则哈希表位置为20%10=2。 接下来,定义一个结构体来表示哈希表中的每个元素,包括关键字和值。 ```c struct hash_element { int key; int value; }; ``` 然后,定义一个哈希表数组,将每个元素插入到哈希表中。如果哈希表位置已经被占用,可以使用链表来解决冲突。 ```c #define HASH_SIZE 10 struct hash_element *hash_table[HASH_SIZE]; void insert(int key, int value) { int index = key % HASH_SIZE; struct hash_element *element = malloc(sizeof(struct hash_element)); element->key = key; element->value = value; if (hash_table[index] == NULL) { hash_table[index] = element; } else { struct hash_element *p = hash_table[index]; while (p->next != NULL) { p = p->next; } p->next = element; } } int search(int key) { int index = key % HASH_SIZE; struct hash_element *p = hash_table[index]; while (p != NULL) { if (p->key == key) { return p->value; } p = p->next; } return -1; } ``` 这里的insert函数将关键字和值封装成一个结构体,然后根据哈希函数计算出哈希表位置。如果该位置为空,直接插入元素;否则,遍历链表直到找到空位置插入。 search函数根据哈希函数计算出哈希表位置,然后遍历链表查找关键字。 以上是一个简单的哈希表实现,可以根据实际需求进行改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值