一个文件,内含一千万行字符串,每个字符串在1K以内,要求找出所有相反的串对,如abc和cba。

现在已经是深夜了,再写个博就睡~

题目据说是百度的一道面试题,找了个网上的代码,自己跑了一遍。

分析如下:

文件的大小上限是10G,不可能在内存操作了。考虑设计一种hash使得如果两个字符串维相反串能得出相同的hash值,然后用该hash将文件中的字符串散列到不同的文件中,再在各文件中进行匹配。比如这样的hash函数对字符串上所有字符的ascii求和,因为长度在1K以内,因此范围在int之内。更进一步,可以在上面那个hash后面再加一个字符串长度,可以得到更好的散列效果。

#include <iostream>
#include <string>
#include <malloc.h>
#include <stdlib.h>
#include <fstream>
using namespace std;

#define ERROR	0

struct _linkList	//hash拉链结构。
{
	char* strValue;
	_linkList* next;
};

void reverse(char* str, int len)
{
	int start, end;
	start = 0;
	end = len-1;
	while(start < end)
	{
		char temp = str[start];
		str[start] = str[end];
		str[end] = temp;
		start++;
		end--;
	}
}

class CHash
{
	_linkList* list[350];	//根据哈希地址构造拉链式哈希表  
public:
	CHash();
	~CHash();
	int HashFunc(char* str);
	void InitHash();
};

CHash::CHash()
{
	int i;
	for (i = 0; i < 350; 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 i;
	for (i = 0; i < 350; i++)
	{
	//	free(list[i]->strValue);
		free(list[i]);
	}
}

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 *= 2;
		}
		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 *head;
			head = list[addr];

			strcpy(tempstr, str);
			reverse(tempstr, strlen(tempstr));

			while (head->next != NULL)	//遍历哈希表拉链 
			{
				head = head->next;
				if (strcmp(tempstr, head->strValue) == 0)
				{
					cout<<head->strValue<<" "<<str<<endl;	//如果读入的字符串反转后与链表中字符串相等,则输出 
					isRight = true;//标志位,字符串已处理。此处标志位的处理要好好学习一下!
					break;
				}
			}
			if (!isRight)	//如果读入的字符串反转后与链表中字符串不相等,则将新结点插入到链表中  
			{
				_linkList* newNode = (_linkList*)malloc(sizeof(_linkList));
				newNode->strValue = new char[10];
				strcpy(newNode->strValue, str);
				//之前用newNode->setValue = str;这样它们就共用一个地址,下次循环时,传入str的值就会将原来的strValue覆盖掉。
				//字符串的赋值一般要用strcpy!
				newNode->next = NULL;
				head->next = newNode;
				//head = newNode;
			}
		}
	}
	fin.clear();
	fin.close();
}

int main()
{
	CHash CH = CHash();
	CH.InitHash();
	return 1;
}



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值