11-散列2 Hashing(浙大数据结构PTA习题)

11-散列2 Hashing        分数 25        作者 陈越        单位 浙江大学

Question:

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%TSize where TSize is 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: MSize (≤104) and N (≤MSize) which are the user-defined table size and the number of input numbers, respectively. Then N 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 -

代码长度限制:16 KB        时间限制:400 ms        内存限制:64 MB

题目解析:

问题大意:创建一个表长为素数的哈希表,采用除留取余法构造散列函数,采用平方探测法(只使用正数序列)解决散列冲突,向此哈希表中插入一个数据,若可以插入,要求输出插入的位置。

关键点1:应用平方探测法解决散列冲突

                                                                                                    (图片来源于慕课浙大数据结构 )

关键点2:如何判断插入不成功的情况

        (1)插入不成功的判断:当平方探测次数等于表长TableSize时,则标志此数据无法插入;

        (2)有定理显示:如果散列表长度TableSize是某个4k+3(k是正整数)形式的素数时,平方探测法就可以探测到整个散列表空间;

        对于以上两个结论,作者现水平有限无法证明,因此先留下这两个问题,希望与诸君讨论。并且对于(1),作者也是从网上获悉,无法保证其正确性,但其对此题的所有测试点是成立的。

参考代码:

# include<stdio.h>
# include<math.h>

int Prime(int N);
int Hash(int Key, int TableSize); 
void InsertTable(int Array[], int Element, int TableSize, int Num, int N); 

int main(){
	int MSize,N;
	scanf("%d %d",&MSize,&N);
	// 创建并初始化散列表 
	int TableSize = Prime(MSize);
	int i,Element,Array[TableSize];
	for(i=0;i<TableSize;i++)Array[i] = -1;
	// 向散列表中插入元素,并输出插入结果
	for(i=0;i<N;i++){
		scanf("%d",&Element);
		InsertTable(Array,Element,TableSize,i+1,N);
	} 
	return 0;
}

// 向散列表中插入元素,并输出元素的位置(为了格式化输出,Num作为插入元素个数的计数,N为要插入元素的总个数)
void InsertTable(int Array[], int Element, int TableSize, int Num, int N){
    // 获取键值
    int Key = Hash(Element,TableSize);
    int Count = 0, Pos = Key;
    while(Array[Pos]!=-1){
        Pos = Key + ((Count+1)/2)*((Count+1)/2);
        if(Pos>=TableSize)Pos%=TableSize;
        Count++;
        // 如果探测次数达到表长,则表示无法插入 
        if(Count == TableSize){
            // 找不到合适的位置进行插入,输出
            if(Num == N)printf("-");
            else printf("- ");
            return;
        }
    }
    // 找到了合适的位置,插入即可
    Array[Pos] = Element;
    // 输出位置信息
    if(Num == N)printf("%d",Pos);
    else printf("%d ",Pos);
    return;
}

// 返回大于等于N的第一个素数
int Prime(int N){
	// 若N为0或1或2,则表长直接设为最小的素数2 
    if(N<=2)return 2;
    int i,j,valid;
    for(i=N;;i++){
        valid = 0;
        for(j=2;j<=(int)sqrt(i);j++){
            if(i % j == 0){
                valid = 1;
                break;
            }
        }
        if(valid == 0)return i;
    }
}

// 散列函数:除留取余法
int Hash(int Key, int TableSize){
    return Key%TableSize;
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值