数据结构与算法-7-43 字符串关键字的散列映射

发布于 / 刷题 / 0 条评论

给定一系列由大写英文字母组成的字符串关键字和素数P,用移位法定义的散列函数H(Key)将关键字Key中的最后3个字符映射为整数,每个字符占5位;再用除留余数法将整数映射到长度为P的散列表中。例如将字符串AZDEG插入长度为1009的散列表中,我们首先将26个大写英文字母顺序映射到整数0~25;再通过移位将其映射为3×322+4×32+6=3206;然后根据表长得到,即是该字符串的散列映射位置。

发生冲突时请用平方探测法解决。

输入格式:

输入第一行首先给出两个正整数N500)和P2N的最小素数),分别为待插入的关键字总数、以及散列表的长度。第二行给出N个字符串关键字,每个长度不超过8位,其间以空格分隔。

输出格式:

在一行内输出每个字符串关键字在散列表中的位置。数字间以空格分隔,但行末尾不得有多余空格。

输入样例1:

4 11
HELLO ANNK ZOE LOLI

输出样例1:

3 10 4 0

输入样例2:

6 11
LLO ANNA NNK ZOJ INNK AAA

输出样例2:

3 0 10 9 6 1

这是一道字符串散列问题,使用平方探测解决冲突即可。

要特别注意一点,题目中要求取最后三位为求散列函数所用的特征,但是有一个测试点的字符串只包含两个字符,特别注意防止数组越界的问题。

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <vector>

using namespace std;

int GetHash(string str){
  int hash = 0;
  for( int i = str.length()-1, p = 0; p <= 2 && i >= 0; i--, p++){
    int add = str[i] - 'A';
    add *= pow(32, p);
    hash += add;
  }
  return hash;
} 

int main(){
  int N, P;
  cin >> N >> P;
  vector<string> H(P);
  for(int i = 0; i < N; i++){
    string input;
    cin >> input;
    int hash = GetHash(input) % P;
    int _hash = hash;  //一会下面hash被改变了,这里备份一个没有被修改的 
    int s = 1, _s = 1;  //s为增量序列,_s为符号(正负号) 
    while(1){
      while(hash >= P) hash -= P;  //右方越界 
      while(hash < 0) hash += P;  //左方越界 
      if(H[hash] == ""){  //插入的位置没有元素 
        H[hash] = input;
        cout << hash;
        if(i!=N-1) cout << ' ';
        break;
      }
      if(H[hash] == input){  //已经ojbk了 
        cout << hash;
        if(i!=N-1) cout << ' ';
        break;
      }
      hash = _hash + _s * pow(s, 2);
      if(_s == 1)
        _s = -1;
      else if(_s == -1)
        _s = 1, s++;
    } 

  }
  return 0;
}

转载原创文章请注明,转载自: 斐斐のBlog » 数据结构与算法-7-43 字符串关键字的散列映射
目前还没有评论,快来抢沙发吧~