文件的大小上限是10G,不可能在内存操作了。考虑设计一种hash使得如果两个字符串维相反串能得出相同的hash值,然后用该hash将文件中的字符串散列到不同的文件中,再在各文件中进行匹配。比如这样的hash函数对字符串上所有字符的ascii求和,因为长度在1K以内,因此范围在int之内。更进一步,可以在上面那个hash后面再加一个字符串长度,可以得到更好的散列效果。
/************************************************************************/
/* 一个文件,内含一千万行字符串,每个字符串在1K以内,
要求找出所有相反的串对,如abc和cba。
思路:使用hash表
*/
/************************************************************************/
#include<iostream>
#include<string>
#include<malloc.h>
#include<stdlib.h>
#include<fstream>
using namespace std;
#define ERROR 0
struct _LinkList//哈希表拉链结构
{
char *strValue;
_LinkList *next;
};
void Reverse(char str[],int len)//字符串反转函数,对字符串进行反转时,要使用数据表示字符串
{
int start,end;
start=0;
end=len-1;
while(start<end)
{
char temp;
temp=str[start];
str[start]=str[end];
str[end]=temp;
start++;
end--;
}
}
class CHash
{
private:
_LinkList *List[350];//根据哈希地址构造拉链式哈希表
public:
CHash();
~CHash();
int HashFunc(char *str);
void InitHash();
};
CHash::CHash()
{
int i;
for(i=0;i<320;i++)
{
List[i]=(_LinkList*)malloc(sizeof(_LinkList));//初始化
if(!List[i])
exit(ERROR);
List[i]->next=NULL;
List[i]->strValue=new char[10];
}
}
CHash::~CHash()
{
}
int CHash::HashFunc(char *str)//哈希函数,将字符串各字符对90取模,取模值为偶数乘权重2,将各值相加作为哈希地址
{
char *p=str;
int sum=0;
while(*p!='\0')
{
int mod=(int)(*p)%90;
if(mod%2==0)
mod=mod*2;
sum=sum+mod;
p++;
}
return sum;
}
void CHash::InitHash()
{
ifstream fin;
ofstream fout;
char str[10];
char tempstr[10];
fin.open("data.txt");
if(fin.is_open())//从文件中读入字符串
{
while(fin>>str)
{
int addr=HashFunc(str);
bool isRight=false;
_LinkList *newNode,*head;
newNode=(_LinkList*)malloc(sizeof(_LinkList));//新建一个结点
if(!newNode)
exit(ERROR);
newNode->next=NULL;
newNode->strValue=new char[10];
strcpy(newNode->strValue,str);//结点赋值
head=List[addr];
strcpy(tempstr,str);//保存下原始字符串
Reverse(str,strlen(str));//将字符串反转
while(head->next)//遍历哈希表拉链
{
head=head->next;
if(strcmp(str,head->strValue)==0)//如果读入的字符串反转后与链表中字符串相等,则输出
{
cout<<head->strValue<<" "<<tempstr<<endl;
isRight=true;//标志位,字符串已处理
break;
}
}
if(!isRight)//如果读入的字符串反转后与链表中字符串不相等,则将新结点插入到链表中
{
head->next=newNode;
head=newNode;
head->next=NULL;
}
}
}
fin.clear();
fin.close();
}
int main()
{
CHash CH=CHash();
CH.InitHash();
return 1;
}
程序中为了验证方便,在文件字符串设定长度为5;
STL的set用什么实现的?为什么不用hash?
是用红黑树实现的,红黑树是一种平衡性很好的二分查找树。要使用hash的话,就需要为不同的存储类型编写哈希函数,这样就照顾不到容器的模板性了,而是用红黑树只需要为不同类型重载operator<就可以了。