poj2503

这道题目是哈希查找的典型题目,先打表后查找,思路非常简单。但是输入中存在许多问题。我开始用的是hash写的,超时了,下面是我哈希的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 999983
struct Node{
	char english[12];
	char foreign[12];
	struct Node *next;
}node[Max];
bool flag[Max];
char source[12];
char target[12];
int slen,tlen;
void Hash(bool trag){
	int key=0;
	for(int i=0;i<tlen;i++)
		key+=(target[i]-'0');
	int pos=key%Max;
	if(!trag){
		if(!flag[pos]){
			flag[pos]=1;
			strcpy(node[pos].english,source);
		    strcpy(node[pos].foreign,target);
			node[pos].next=NULL;
		}
		else{
			struct Node *index=(struct Node*)malloc(sizeof(struct Node));
			strcpy(index->english,source);
			strcpy(index->foreign,target);
			index->next=node[pos].next;
			node[pos].next=index;
		}
	}
	else{
		if(!flag[pos])
			printf("eh\n");
		else{
			struct Node *index=&node[pos];
		    while(index!=NULL){
				if(strcmp(index->foreign,target)==0){
					printf("%s\n",index->english);
					return ;
				}
				index=index->next;
			}
			printf("eh\n");
		}
	}
}
int main(){
	memset(flag,0,sizeof(flag));
	char str;
	int slen,tlen;
	bool sym;
	while(true){
		str=getchar();
		if(str=='\n')
			break;
		slen=0;
		source[slen++]=str;
		sym=0;
		while(true){
			str=getchar();
			if(str==' '){
			    sym=1;
				tlen=0;
				continue;
			}
			if(str=='\n')
				break;
			if(!sym)
				source[slen++]=str;
			else
				target[tlen++]=str;
		}
		source[slen]='\0';
		target[tlen]='\0';
		Hash(0);
	}
	tlen=0;
	
	while(true){
		str=getchar();
		if(str=='\n')
			break;
	    tlen=0;
		target[tlen++]=str;
		while(true){
		str=getchar();
		if(str=='\n')
			break;
		target[tlen++]=str;
		}
		target[tlen]='\0';
		Hash(1);
	}
	return 0;
}


后来用map映射做,1532ms,17340K下面是代码:

#include <iostream>
#include <string>
#include <map>
using namespace std;
map<string,bool> flag;
map<string,string> check;
char source[20];
char target[20];
int slen,tlen;
int main(){
	char str;
	bool sym;
	while(true){
		str=getchar();
		if(str=='\n')
			break;
		slen=0;
		source[slen++]=str;
		sym=0;
		while(true){
			str=getchar();
			if(str==' '){
			    sym=1;
				tlen=0;
				continue;
			}
			if(str=='\n')
				break;
			if(!sym)
				source[slen++]=str;
			else
				target[tlen++]=str;
		}
		source[slen]='\0';
		target[tlen]='\0';
		flag[target]=true;
		check[target]=source;
	}
	/*while(true){
		str=getchar();
		if(str=='\n')
			break;
	    tlen=0;
		target[tlen++]=str;
		while(true){
		str=getchar();
		if(str=='\n')
			break;
		target[tlen++]=str;
		}
		target[tlen]='\0';
		if(flag[target])
			cout << check[target] << endl;
			//printf("%s\n",check[target]);
		else
			//printf("en\n");
			cout << "eh" << endl;
		
	}*/
	while(cin >> target){
		if(flag[target])
			cout << check[target] << endl;
			//printf("%s\n",check[target]);
		else
			//printf("en\n");
			cout << "eh" << endl;
	}
	return 0;
}


仔细分析了一下,map交hash算法的时间优势(空间优势很明显)

1)首先map在输入english和foreign时,是来一个存一个,不需要比较,而哈希每输入一个都要进行比较,并且要耗时求key。

2)然后就是输出阶段,map直接根据映射关系判断是否存在foreign,而哈希则要求key值,比较,然后得出输出

相较而言,map的时间优势主要体现在输出阶段。

最后我又写了一个快排+二分的算法,2544k+829ms,时间和空间更优化了。

下面是代码:

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
#define Max 100010
typedef struct Node{
	char english[12];
	char foreign[12];
}node;
node record[Max];
bool cmp(const node &p,const node &q){
	 if(strcmp(p.foreign,q.foreign)<0)
		return 1;
	 return 0;
}
int slen,tlen;
char source[12],target[12];
void find(int n){
	int left=0,right=n-1,middle;
    while(left<=right){
		middle=(left+right)/2;
		if(strcmp(record[middle].foreign,target)<0)
			left=middle+1;
		else if(strcmp(record[middle].foreign,target)==0){
			//printf("%s\n",record[middle].english);
			cout << record[middle].english << endl;
			return ;
		}
		else
			right=middle-1;
	}
	//printf("eh\n");
	cout << "eh" << endl;
}
int main(){
	char str;
	bool sym;
	int  index=0;
	while(true){
		str=getchar();
		if(str=='\n')
			break;
		slen=0;
		source[slen++]=str;
		sym=0;
		while(true){
			str=getchar();
			if(str==' '){
			    sym=1;
				tlen=0;
				continue;
			}
			if(str=='\n')
				break;
			if(!sym)
				source[slen++]=str;
			else
				target[tlen++]=str;
		}
		source[slen]='\0';
		target[tlen]='\0';
		strcpy(record[index].english,source);
		strcpy(record[index++].foreign,target);
	}
	sort(record,record+index,cmp);
	//for(int i=0;i<index;i++)
		//printf("%s\n",record[i].foreign);
	while(cin >> target)
		find(index);
	return 0;
}


分析map和快排+二分的时间复杂度,我发现一个很奇怪的现象:

快排输入阶段和map一样,输入完毕要sort排序,时间多消耗1000log1000,输出阶段还要二分查找,因此理论上来说map要快一些,实际上快排却更快,原因就只可能是map本身这种数据结构就很耗时,具体原理可以参考STL标准程序库,这里不详细介绍了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值