PTA 11-散列2 Hashing (25分)

The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers. The hash function is defined to be H(key) = key \% TSizeH(key)=key%TSize where TSizeTSizeis the maximum size of the hash table. Quadratic probing (with positive increments only) is used to solve the collisions.

Note that the table size is better to be prime. If the maximum size given by the user is not prime, you must re-define the table size to be the smallest prime number which is larger than the size given by the user.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive numbers: MSizeMSize (\le 10^4104) and NN (\le MSizeMSize) which are the user-defined table size and the number of input numbers, respectively. Then NN distinct positive integers are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the corresponding positions (index starts from 0) of the input numbers in one line. All the numbers in a line are separated by a space, and there must be no extra space at the end of the line. In case it is impossible to insert the number, print "-" instead.

Sample Input:

4 4
10 6 4 15

Sample Output:

0 1 4 -




—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————这道题目我遇到的一点问题:

对于平方探测,如果散列表长度是4k+3形式的素数,平方探测法可以探查到整个散列空间,但是这里的题目给出的是素数,因此存在散列表内即使有空间,也不能放进去的情况,我想的时候主要是在考虑什么情况下才能判断这个元素即使增量一直增大也不能放进去呢?

后来看了下别人写的,自己再推了下:

假设散列表大小为Size,那么当增量大于等于Size平方的时候就是在重复之前1平方,2平方...到(size-1)平方的事情。只要把Size平方,(Size+1)平方因式分解一下,就会发现对求余有影响的就是Size加的部分,后面就是一直重复了。所以有了:

if(CNum>=H->TableSize)
		{
			NewPos=-1;
			break;
		}
NewPos=-1表示不存在这个位置。

还有一点就是:测试点中有一个是输入 1 1,那么对于你求素数那部分的函数,必须把1的特殊情况也考虑进去。

下面给出AC的代码

#include "stdio.h"
#include "stdlib.h"
#define ElementType int
typedef unsigned int Index;
int flag=1;                //标志位,输出用
enum EntryType
{
	Legitimate,Empty,Deleted
};

typedef struct HashEntry Cell;
struct HashEntry
{
	ElementType Element;
	enum EntryType Info;
};

typedef struct HashTbl* HashTable;
struct HashTbl
{
	int TableSize;
	Cell* TheCells;
};
int isPrime(int x)
{
	if (x == 1)return 0;  
	for (int i = 2; i < x; i++)
		if (x % i == 0)
			return 0;  
	return 1;  
}  
int NextPrime(int x)
{
	while (!isPrime(x))
		x++;  
	return x;  
}  

HashTable CreateHash(int N)         //创建一个空的hashtable
{
	int i;
	HashTable H;
	H=(HashTable)malloc(sizeof(struct HashTbl));
	H->TableSize=NextPrime(N);
	H->TheCells=(Cell*)malloc(H->TableSize*sizeof(Cell));
	for(i=0;i<H->TableSize;i++)
		H->TheCells[i].Info=Empty;
	return H;
}

int Hash(int key,int p)
{
	return key%p;
}

Index Find(ElementType Key,HashTable H)
{
	Index CurrentPos,NewPos;
	int CNum=0;               //记录冲突次数
	NewPos=CurrentPos=Hash(Key,H->TableSize);
	while((H->TheCells[NewPos]).Info!=Empty&&H->TheCells[NewPos].Element!=Key)
	{
		CNum++;
		NewPos=(CurrentPos+CNum*CNum)%H->TableSize;
		if(CNum>=H->TableSize)
		{
			NewPos=-1;
			break;
		}
	}

	return NewPos;
}

void Insert(ElementType Key,HashTable H)
{
	Index Pos=Find(Key,H);
	if(flag)       
	{
		if(Pos==-1)
			printf("-");
		else
		{
			H->TheCells[Pos].Info=Legitimate;
			H->TheCells[Pos].Element=Key;
			printf("%d",Pos);
		}
		flag=0;
		return;
	}
	else
	{
		if(Pos==-1)
			printf(" -");
		else
		{
			H->TheCells[Pos].Info=Legitimate;
			H->TheCells[Pos].Element=Key;
			printf(" %d",Pos);
		}
		return;
	}
}
int main()
{
	int i,M,N,element;
	HashTable H;
	scanf("%d%d",&M,&N);
	H=CreateHash(M);
	for(i=0;i<N;i++)
	{
		scanf("%d",&element);
		Insert(element,H);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值