使用双哈希统计单词数目

使用双哈希统计单词数目

给定一个txt文本文档,其格式为每行一个单词,统计出现的单词数目并输出到屏幕上,同时输出程序运行时间,将单词及出现次数保存到一个txt文档中。
先对每一个单词进行两次不同的哈希,然后按第一个哈希值进行堆排序,之后再第一个哈希值相同的范围的进行第二次堆排序,遍历,如与中间保存的单词两个哈希值都相同,次数加一然后跳过,反之,统计这个单词。

  • create&edit by GongXiaolin
    2019.12.9.14:23*/
    /deal the string to a hash value,then duipaixu/

/edit again 12.20 13:23/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<string.h>
#define p 3145739
#define mod 50331653
#define hash0 12582917
#include
using namespace std;
typedef struct word{

char ch[25];
unsigned int hashval;
unsigned int hashval2;
}word;

word list[12000000];
long length=0;

unsigned int hashfun2(char *str)//BKDR HASH
{
unsigned int seed = 131313;//也可以乘以31、131、1313、13131、131313…
unsigned int hash = 0;
while(str)
{
hash = hash
seed + (str++);
}
return hash%0x7FFFFFFF;//MAX代表hash表长度
}
unsigned int DJBHash(char str){
unsigned int hash=5381;
while(str){
hash += (hash << 5) + (str++);
}
return (hash & 0x7FFFFFFF);
}
unsigned int hashfun1(char ch[]){
int i;
i=0;
unsigned int sum=0;
for(i;ch[i]!=’\0’;i++){
sum=sum+DJBHash(ch[i])
(unsigned int)(i+1);

}
return sum;

}

void readandhash(word list[],FILE *TXT,long *i){
*i=0;
long j;
j=0;
char cha[25];
char chb[25];
int l;
while(fgets(cha,25,TXT)!=NULL){
l=strlen(cha);
cha[l-1]=’\0’;
strcpy(list[j].ch,cha);
strcpy(chb,cha);

list[j].hashval=hashfun1(cha)+ELFHash(cha);
list[j].hashval2=hashfun2(cha);
j=j+1;
}
*i=j;

}

void heapify(word list[],long i,long j){
long k;
word x;
k=2i;
x=list[i];
while(k<=j){
if(k<j)
if(list[k].hashval<list[k+1].hashval)k=k+1;
if(x.hashval>=list[k].hashval)
break;
else {
list[i]=list[k];
i=k;
k=2
i;
}
}
list[i]=x;
}

void heap_sort(word list[],int n,int m){
int i;
word x;
for(i=(n+m)/2;i>=(m+1);i–)heapify(list,i,n);
for(i=n;i>(m+1);i–)
{
x=list[1];

list[1]=list[i];

list[i]=x;

heapify(list,1,i-1);
}
}

void heapifyinpart(word list[],long *length){
long i=0;
long j=0;
while(i<=*length && j<=*length){
while(list[j].hashval==list[i].hashval)j=j+1;
heap_sort(list,j-1,i);
i=j;
}
}

void GET(word list[],long i)
{ //结果输出
long j=0;
long num=1;
long sum=0;
word x;
FILE *FP;
FP=fopen(“文本1.txt”,“w”);
x=list[j];
for(j=1;j<=i;j++)
{
if(x.hashvallist[j].hashval && x.hashval2list[j].hashval2 && ) /一样的加一,不一样的输出并统计/
{
num=num+1;
continue;
}
//fprintf(FP,"%s出现%ld次\n\n",x.ch,num);
num=1;
sum=sum+1;
x=list[j];
}
printf(“共出现单词%ld个”,sum);}

int main(){
clock_t start,finish;
start=clock();
double time;//开始计时
FILE *txt;
//errno_t err;
txt=fopen(“C:\Users\13753\Desktop\wordtxt.txt”,“r”);
readandhash(list,txt,&length);
heap_sort(list,length,0);
heapifyinpart(list,&length);
FILE *I;
I=fopen(“文本2.txt”,“w”);
int i;
//for(i=0;i<=length;i++)fprintf(I,"%d==%-25s hash1 %-15u hash2 %-64u \n",i,list[i].ch,list[i].hashval,list[i].hashval2);
GET(list,length);
fclose(txt);
finish=clock();
time=(double)(finish-start)/CLOCKS_PER_SEC;
printf(“程序执行了%lfms”,time);

}

方法特点是运行速度快,10万个单词统计时间为0.几ms,100万为10余毫秒,1000万为50余毫秒。其时间复杂度为O(nlogn)
但是由于哈希值的冲突,无法保证统计完全正确。目前测试为1/6500000的出错率。

这是10万个单词的统计结果

这是输出的TXT文档

1000万个单词统计情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值