拉链法解决冲突的哈希表

http://poj.org/problem?id=3349

题目描述:找是否有两片完全相同的雪花,雪花总数为 0 < n ≤ 100000,判断两片雪花是否相同的标准为其中一片雪花的的六角数组经过向左(右)循环移位后与另一片的六角数组相同

下述方法的一个改进是用空间换取时间,即将雪花的六角存储两份在一个 size 为 12 的数组中,判断另一片要雪花数组是否在其中,然后将两一片雪花数组逆序,再判断一次、

逆序有一种较为巧妙的方法,不用辅助空间,如下

reverse( int a[] , size ){
	for( int i = 1, i <= size / 2; i ++ ){
		a[i] = a[i] ^ a[size - i];
		a[size - i] = a[i] ^ a[size - i];
		a[i] = a[i] ^ a[size - i];
	}
}


#pragma warning (disable:4786) 
#include<stdio.h> 
#include<iostream>
#include<string>
using namespace std;
#define rem 9991      //hash时取模的大质数
bool flag = false;    //是否有重复的数
雪花
struct snow{
	int lens[6];      //雪花有六个角
	snow * next;      //使用拉链法解决哈希冲突
};
表头
struct head{
	snow * next;
};
head h[rem + 1];
清空hash表
void init(){
	int i;
	for( i = 0; i < rem; i ++ ){
		h[i].next = NULL;
	}
}
哈希函数
int hash( int lens[] ){
	int sum = 0;
	//这种方法只适用于此题
	sum = (lens[0] + lens[2] + lens[4])^(lens[1] + lens[3] + lens[5]);   
	
//	for( i = 0; i < 6; i ++ )
//		sum = sum + lens[i];

	return sum % rem;
}

判断两片雪花是否相同,即其中一片雪花的的六角数组经过向左(右)循环移位后与另一片的六角数组相同
bool judge( int a[], int b[] ){
	int i,j;
    for(i=0;i<6;i++)
    {
        if(a[0]==b[i])
        {
            for(j=1;j<6;j++)
                if(a[j]!=b[(j+i)%6])
                  break;

            if(j==6) return 1;

            for(j=1;j<6;j++)
				if(a[6-j]!=b[(i+j)%6])
				 break;

            if(j==6) return 1;
        }
    }
	return 0;
}

在链表里寻找是否有完全相同的另一片雪花,有返回true
bool search( head * h, int lens[8] ){
	snow * temp = h->next;
	snow * p = NULL;      // p 指向当前访问链表节点的上一个节点
	
	while( temp != NULL )
	{			
		if( judge( lens, temp->lens ) )
			return true;

		p = temp;
		temp = temp -> next;
	}

	//没有找到重复节点,则插入该节点
	temp = new snow;
	for( int j = 0; j < 8; j ++ )
		temp->lens[j] = lens[j];
	temp->next = NULL;
	if( p != NULL )
		p->next = temp;
	else h->next = temp;

	return false;
}

int main(){
	int i,j,n;
	init();

	下面的这段读输入的程序在G++上比直接 scanf("%d",&len[j]) 的速度快一倍以上
	char c;
	cin>>n;
        c=getchar();
	for(i=1;i<=n;i++)
	{
		int lens[6];
		for(j=0;j<=5;j++)
		{
		    int	x=0;
			c=getchar();
			while(c!=' '&&c!='\n')
			{
				x=x*10;
				x+=(c-48);
				c=getchar();
			}
			lens[j] = x;
		}
     读输入的程序结束   
    
		if( !flag ){
			哈希并查找重复
			int index = hash( lens );
			flag = search(  &h[index], lens );
		}
	}
	if( ! flag )
		printf("No two snowflakes are alike.\n");
	else 
		printf("Twin snowflakes found.\n");
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值